Having spent some time trying to work out why Moodle 1.53 was not automatically assigning people (by group membership) as course creators, it looks like something is wrong in auth\ldap\lib.php.
According to bugid 3931 it should work in 1.53 but I couldn't make it, having searched here and found references to "memberOf" as the the required value for ldap_memberattribute, I tried this, no luck.
Eveantually I found in lib.php
function auth_ldap_getdefaults
which (for 'ad') also sets ldap_memberattribute to "memberOf"
and sets ldap_memberattribute_isdn to 0.
For the purpose of group membership checking in auth\ldap\lib.php these are incorrect (AFAIUI).
"memberOf" is a property of a user object, i.e. memberOf cn=xyz (etc.) group
The property required for looking at a group to find members is simply "member".
Also, when looking at groups for members, the members are stored as distinguished names (e.g. cn=Jim Smith,ou=peeps,dc=home,dc=local) not just username (e.g. SmithJ). So for Active Directory, ldap_memberattribute_isdn should be 1.
Have I missed something somewhere, or are the default values used elsewhere and is changing them to what I believe they should be, going to break something ?
ATM there's not public/visible way to set ldap_memberattribute_isdn, shouldn't this be configurable on the LDAP authentication page ? - I can't see how any(normal)body could have this feature working on Windows servers.
Have I missed something ?
Tim
Nope. We need your help testing things on AD. So far, the programmers working on Auth/LDAP and Enrol/LDAP have Moodle installs running with OpenLDAP or eDirectory. So the accuracy of our AD settings isn't really that good
That changes quickly as soon as someone can post a good patch here (is that a hint or something?) Have you been able to get it going against AD? Can you post a good unified diff against 1.5.3+ showing the minimal changes required for it to work?
The property required for looking at a group to find members is simply "member".
Oops!. My fault. It was me who proposed that change (member->memberOf) a couple of months ago. I thought it was used to test membership of users, not to list users belonging to a group. I was obviously wrong.
I have also verified that members are indeed DN values (with ADSI Edit), as Tim says.
Martin, would you please revert that change? (I have attached a diff that reverts the change and makes ldap_memberattribute_isdn = 1 for AD).
Tim, as for the setting of ldap_memberattribute_isdn, you could add something like this to you config.php file in the meanwhile:
$CFG->ldap_memberattribute_isdn = 1;Saludos. Iñaki.
Tim -- can you confirm that vanilla 1.5.3 with Iñaki's patch does the trick for you? I will only merge the fix when I hear from both of you that it works...
For future reference, is there a way to apply patches (I just made the changes by hand) - in Windows land ?
Saludos. Iñaki.
Saludos. Iñaki.
If the defaults section (of ldap\lib.php) can be guaranteed to be correct for all choices of server, then there would be no need to set either value indvidually.
This was an extremely helpful post! I have been testing the moodle system from various operating systems against our MS AD tree and the whole process of course creators was puzzling me due to its lack of operation. I performed the simple change to the lib.php and all of sudden my teachers were able to automatically become course creators.
Bravo chaps!
Hi,
I'm using a similar setup - moodle on windows server 2003 and MS AD for LDAP lookups. We can get the lookups to work, but the course creator thingy is stubbornly dead. It even reverts any manual changes that are made. Our teachers are in ou=teachers,ou=staff,dc=pmsnet,dc=internal and that's ok for the sign-on, but is this the same thing that should be put into the course creators box? We apparently can only make security groups and distribution groups, not posixgroups as mentioned in the moodle docs page. Checking my member attributes on the AD server, I'm in cn=staff,dc=pmsnet,dc=internal but this doesn't work either. It also doesn't work with ldap_memberattribute set to memberOf and/or
set in config.php.
Could anyone advise on how to get this to work? It's driving me nuts (not to mention the rest of the IT team).
Thanks,
Matt
Found the soultion!
the correct group procedure using MS AD is to create a security group, add the people, and then list all of the OUs, preceded by the security group e.g.
cn=Staff-creators,ou=teachers,ou=staff,dc=pmsnet,dc=internal; cn=Staff-creators,ou=admin,ou=staff,dc=pmsnet,dc=internal
hope that saves someone some hassle.
Matt
if ($info[0]["member"][$i] === $username){
$result = true;
}
}
I wanted to report this as a bug, but I ultimatly was unable to determine if it was an issue with my setup or the code. Attched is my modified lib.php
Saludos. Iñaki.
Here are my settings: I if you see discrepancies from yours that may affect this please let me know…
ldap_host_url: |
ldap://myserver.mydomain.com/ |
ldap_version: |
3 |
ldap_preventpassindb: |
Yes |
ldap_bind_dn: |
cn=moodlebind,ou=Tech Center,dc=mydomain,dc=com |
ldap_bind_pw: |
******** |
ldap_user_type: |
MS DctiveDirectory |
ldap_contexts: |
ou=Tech Center,dc=mydomain,dc=com |
ldap_search_sub: |
No |
ldap_opt_deref: |
No |
ldap_user_attribute: |
SAMAccountName |
ldap_memberattribute: |
|
ldap_objectclass: |
|
Force change password: |
No |
Use standard Change Password Page: |
No |
ldap_expiration: |
No |
ldap_expiration_warning: |
10 |
ldap_exprireattr: |
|
ldap_gracelogins: |
No |
ldap_graceattr: |
|
ldap_create_context: |
|
ldap_creators: |
CN=Domain Admins,OU=Tech Center,DC=mydomain,DC=com |
mysqlversion 5.0.19
phpversion 4.3.10
php_extensioniconv is enabled OK
php_extensionmbstring is enabled OK
Thank you for taking the time to look at this information.
James Bromley
Ok, I get the idea it Just Works(tm) for you but it is not just working for me or I would not of gotten here... Please help me to find what I have not done that you have (or I did that you did not) that caused mine to Just Not Work this time. (Please excuse my sarcasm)
I am thinking a difference in the PHP setup or something that was not allowing it to enumerate the array of members. Please help me work through this issue. The work around I implemented is only a band-aid.
Thank you for your help!
James Bromley- My W2K3 A.D. domain was upgraded from an existing NT Domain instead of being a fresh install. I don't think this makes any difference.
- I'm mapping 'sAMAccountName' into 'ID Number' (I've just removed this mapping, deleted it from the users' profiles and logged in again, and it works too).
- My creator groups don't have any spaces in their CN's and sAMAccountName's (I'm right now testing with a new group with spaces just to see if it makes any difference. And it doesn't, it works like a charm too.).
- I'm using multiple user contexts with ldap_search_sub = yes. I don't think this could make a difference (your setup is simpler, so there is even less room for error).
- My Moodle 1.6 test site was installed from scratch, not upgraded from 1.5.x. This could or could not make a difference (I have not had a look at the code). It has not been migrated to UTF-8, by the way.
Just to make sure, is your LDAP creator group a global security group?
Saludos. Iñaki.
Yes, cn=nbecmoodlecreator,ou=STAY,ou=Alternative,ou=Administration,dc=mydomain,dc=com is a Global Security Group. You mentioned spaces, neither my creator group or my samaccountname has spaces in it, some of our ou's do. A lot of our samaccountnames's contain a period though. I would not think this to matter. We are using the same version of PHP, and I would not think mysql to matter. The only difference left I see is IIS/MS for the web server vs. apache/linux. Also not on the top of my list for differences. I did upgrade from 1.5.3 to 1.6. I also am running a AD that was migrated from an nt domain. I just tried copping my auth/ldap/lib.php from the 1.6 install to my site and it stopped working. (just in case it did not get copied over when I upgraded.) I am really at a loss I do not see a large difference in our setup's that would be causing this problem... I appreciate your time with this...
James
//echo "Checking group $group for member $username\n"; echo "<!--\n";Saludos. Iñaki.
echo "group: $group \n";
echo "filter: (".$CFG->ldap_memberattribute."=".$username.")\n";
echo "attribs: \n";
print_r ($attribs);
echo "-->\n";
$search = @ldap_read($ldapconnection, $group, '('.$CFG->ldap_memberattribute.'='.$username.')', array($CFG->ldap_memberattribute));
group: CN=Domain Admins,OU=Tech Center,DC=mydomain,DC=com
filter: (member=CN=Bromley\, James,OU=Tech Center,DC=mydomain,DC=com)
attribs:
group: cn=nbecmoodlecreator,ou=STAY,ou=Alternative,ou=Administration,dc=mydomain,dc=com
filter: (member=CN=Bromley\, James,OU=Tech Center,DC=mydomain,DC=com)
attribs:
Above are the results, The first one should of been a match... if I look in phpLDAPadmin at the members of Domain Admins the following is shown...
CN=Bromley\, James,OU=Tech Center,DC=mydomain,DC=com
I am lost, I keep wanting to run to the filter... but I can not put my finger on it...
Thank you for your help with this, Let me know what you think...
James Bromley
//echo "Checking group $group for member $username\n"; echo "<!--\n";Saludos. Iñaki.
echo "group: $group \n";
echo "filter: (".$CFG->ldap_memberattribute."=".$username.")\n";
echo "attribs: \n";
print_r (array($CFG->ldap_memberattribute));
$search = @ldap_read($ldapconnection, $group, '('.$CFG->ldap_memberattribute.'='.$username.')', array($CFG->ldap_memberattribute)); print_r ($search); if (!empty($search) AND ldap_count_entries($ldapconnection, $search)) { $info = auth_ldap_get_entries($ldapconnection, $search); print_r ($info); if (count($info) > 0 ) { // user is member of group $result = true; break; } } echo "-->\n";
group: CN=Domain Admins,OU=Tech Center,DC=mydomain,DC=com
filter: (member=CN=Bromley\, James,OU=Tech Center,DC=mydomain,DC=com)
attribs:
Array
(
[0] => member
)
group: cn=nbecmoodlecreator,ou=STAY,ou=Alternative,ou=Administration,dc=mydomain,dc=com
filter: (member=CN=Bromley\, James,OU=Tech Center,DC=mydomain,DC=com)
attribs:
Array
(
[0] => member
)
I double checked I did put the "print_r ($info);" in it did not print I assume because $search was empty.
James
auth_ldap_get_userdn() returns the right value (as your print_r shows), but don't ask my why, OpenLDAP libraries[1] want that quote with a double backslash.
So with a CN of:
CN=Bromley\, James,OU=Tech Center,DC=mydomain,DC=com
the search fails, but with:
CN=Bromley\\, James,OU=Tech Center,DC=mydomain,DC=com
the search is successful and you get your prize
This is why I wasn't having the problem: none of my CN have ',' in them (in fact, they are just alphanum character strings).
So the magic incantation is adding the following line (the one in blue):
if ($CFG->ldap_memberattribute_isdn) {
$username=auth_ldap_find_userdn($ldapconnection, $username);
}
if (! $username ) {
return $result;
}
$username = preg_replace ('/\\\\,/', '\\\\\\\\,', $username);
$groups = explode(";",$groupdns);
At least it works in the tests I have done here. Maybe we should file a bug with this info if it works in your environment.
Saludos. Iñaki.
[1] I have tested this using the command line version of ldapsearch, and you need the same double backslash syntax there too.
Thank you again for your support,
James Bromley
It was you who found the bug, so it yours . When you open it, put a link to this thread to help understand and fix it, please.
Saludos. Iñaki.
http://moodle.org/bugs/bug.php?op=show&bugid=6060&pos=0
James Bromley
Wow - this thread almost fixed my identical problem. But not quite.
LDAP user authentication is working fine. My user is a member of Moodle Creators and Domain Admins and I've tried both of these in the LDAP setup. Nothing has a comma in it and I've made the change to config.php too.
Brand new moodle, php5 and mysql5.
Is it worth me making the various changes in blue from earlier in the thread to see what info I get? I will anyway!
Colin
Doh! Should have taken my own advice and tried the "blue script" first. All working fine now. The script showed that my moodle creators security group had been created in security groups rather than within staff. Sorted this, removed the other mods and all works absolutely brilliantly.
Thanks for all the work you guys already did as this sorted the bulk of the issue.
Colin
The PHP function ldap_get_dn near line 1386 is responsible for returning the dn with the comma escaped with only one backslash which is not compatible with the filter for ldap_read? I wonder if a different version of PHP makes any difference.
My last question is should this be a few lines higher up in the code would we want to perform this to every username or only to usernames that are dn’s? If so change:
if ($CFG->ldap_memberattribute_isdn) {
$username=auth_ldap_find_userdn($ldapconnection, $username);
}
if (! $username ) {
return $result;
}
$username = preg_replace ('/\\\\,/', '\\\\\\\\,', $username);
$groups = explode(";",$groupdns);
To
if ($CFG->ldap_memberattribute_isdn) {
$username=auth_ldap_find_userdn($ldapconnection, $username);
$username = preg_replace ('/\\\\,/', '\\\\\\\\,', $username);
}
if (! $username ) {
return $result;
}
$groups = explode(";",$groupdns);
Thank you,
James Bromley
In fact, I would change it to:
if ($CFG->ldap_memberattribute_isdn) { $username=auth_ldap_find_userdn($ldapconnection, $username); if (! $username ) { return $result; } $username = preg_replace ('/\\\\,/', '\\\\\\\\,', $username); }The only way $username can be empty at this point is if we can't find the user DN (we already tested before that $username was not empty), so testing it after the ldap_memberattribute_isdn test is "useless".
Thus we only do the 'quoting' if $username should be a DN and we really found that DN in the LDAP server.
Saludos. Iñaki.