Populating Moodle users via Active Directory (LDAP)

Populating Moodle users via Active Directory (LDAP)

by Mike Edwards -
Number of replies: 32
I'm having a few issues getting my test moodle installation to happily populate moodle users from an Active Directory.

LDAP Authentication is currently enabled, and manually created users with auth set to LDAP can authenticate correctly.

My ldap contexts is:ou=Campus Accounts,dc=some_ad,dc=some_school,dc=edu

This is where all the accounts created for campus reside, there's +50K accounts here.

Can moodle automatically create moodle user accounts for people when they first login?
How can I limit this access to members of a central group? Like; cn=moodleAccounts,ou=myOU,dc=some_ad,dc=some_school,dc=edu

I attempted to use the auth_ldap_sync_user script but I'm getting bonged on exceeding the sizelimit of returned results - which appears to be set on the AD to 1000 (I can't change this). I attempted to set the ldar_create_context to a group like the one above but wasn;t getting anywhere. If I need to use this how can I restrict moodle to a single group for user creation?

Any help would be appreciated!

oops - running Moodle 1.5.2, on SLES8 w/ Apache 2.0.54, mysql 4.0.x.

Mike
Average of ratings: -
In reply to Mike Edwards

Re: Populating Moodle users via Active Directory (LDAP)

by Martín Langhoff -
Bummer! If AD has a sizelimit, then the auth_ldap_sync_user script won't work.

Moodle _will_ create the accounts when people login for the first time, no problem with that. It can limit to users on a particular leaf (your LDAP context), but not to members of a group. You may be able to hack that in.
In reply to Martín Langhoff

Re: Populating Moodle users via Active Directory (LDAP)

by Mike Edwards -
Hmmmm, ok for some weird reason my moodle has decided not to create accounts for people who can authenticate correctly (it just stops or complains that it can't find the index.php page...) - I'm tracing through the code to see what its barfing on exactly.  I'll report back as to my level of success.  I really wouldn't care if I can't restrict access to moodle via AD groups - I've gotten a SOAP based auth/auth method to use on our AD so I can always insert the authorization call into the LDAP code and deny based off that.

thanks,
Mike
In reply to Mike Edwards

Re: Populating Moodle users via Active Directory (LDAP)

by Martín Langhoff -

ok for some weird reason my moodle has decided not to create accounts for people who can authenticate correctly

I'm keen on debugging this one through. If you can set debug on, and watch the apache logs...

In reply to Martín Langhoff

Re: Populating Moodle users via Active Directory (LDAP)

by Mike Edwards -
ok I've been debugging all the way through and it seems to not make the @ldap_close($ldapconnection); call at the end of the LDAP lib.php's auth_get_userinfo function. This seems to just hang indefinitely and not allow me to proceed. If I create an accout manually and set its Auth type to LDAP I have no issues authenticating. Here's my nonsensical debugging logs:

Username= mwedward
AUTH= ldap
Creating mwedward
Create_user_record
auth_get_userinfo exists
Username=mwedward in LDAP Auth_get_userinfo
User_DN: CN=mwedward,OU=Campus Accounts,DC=some_ad,DC=some_school,DC=edu
user_info_result= Resource id #31
Key= Michael Value= givenname
Key= Edwards Value= sn
Key= mwedward@some_sc.edu Value= mail
Key= mwedward Value= sAMAccountName
Before LDAP_Close
LDAP_Connection= Resource id #27
#################Dies here - no LDAP close
Username= admin
AUTH= manual
#################Logged in as admin and created my accoutn manually
Username= mwedward
AUTH= ldap
Username=mwedward in LDAP Auth_get_userinfo
User_DN: CN=mwedward,OU=Campus Accounts,DC=some_ad,DC=some_school,DC=edu
user_info_result= Resource id #44
Key= Michael Value= givenname
Key= Edwards Value= sn
Key= mwedward@some_school.edu Value= mail
Key= mwedward Value= sAMAccountName
Before LDAP_Close
LDAP_Connection= Resource id #40
After LDAP_Close
Username= mwedward
AUTH= ldap
Username=mwedward in LDAP Auth_get_userinfo
User_DN: CN=mwedward,OU=Campus Accounts,DC=some_ad,DC=some_school,DC=edu
user_info_result= Resource id #43
Key= Michael Value= givenname
Key= Edwards Value= sn
Key= mwedward@some_school.edu Value= mail
Key= mwedward Value= sAMAccountName
Before LDAP_Close
LDAP_Connection= Resource id #39
After LDAP_Close

Why is it different when comming from an account creation path vs a straight authentication path?

Mike
In reply to Mike Edwards

Re: Populating Moodle users via Active Directory (LDAP)

by Martín Langhoff -
Interesting...

Not surewhy it is different. What happens if you comment out the ldap_disconnect?
In reply to Martín Langhoff

Re: Populating Moodle users via Active Directory (LDAP)

by Mike Edwards -
It still doesn't seem to finish returning.  What's irking me now is that somehow I got it to work last night and then this morning while pulling out my comments to do a diff and see what changed I accidentally lost the original working file....

time passes and I scratch my head.

Ok I know what made it work.  I added a single line to dump out info to my logfile from the create_user_record function.  I added a line to print the $newinfo variable out to a file before the IF statement where it is set to auth_get_userinfo($username).  For some reason if I pull out everything else I have and add this line in it still won't work.

This is totally random.  I'm attaching a diff -u from the stock 1.5.2 moodlelib.php and my modified one.

Mike


In reply to Martín Langhoff

Re: Populating Moodle users via Active Directory (LDAP)

by Iñaki Arenaza -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Bummer! If AD has a sizelimit, then the auth_ldap_sync_user script won't work.

You can change that limit as shown here: http://www.openldap.org/lists/openldap-software/200206/msg00627.html

Or you could change the script to use paged results -see RFC 2696- (I think you need openldap 2.2.* client libraries for this at least).

Saludos. Iñaki.
In reply to Iñaki Arenaza

Re: Populating Moodle users via Active Directory (LDAP)

by Martín Langhoff -
That's a great find Iñaki!

I did look into paged results a while ago, mainly to avoid swamping memory, but the PHP LDAP libraries don't support them sad
In reply to Martín Langhoff

Re: Populating Moodle users via Active Directory (LDAP)

by Iñaki Arenaza -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
I did look into paged results a while ago, mainly to avoid swamping memory, but the PHP LDAP libraries don't support them

I have just looked at it (3+ hours of googling and source code reading of both openldap libraries and PHP-4.3.10 ldap extension ;) and it seems it should be posible (theoretically from PHP 4.0.3 onwards, provided local openldap libraries support it, which you can get for sure from 2.2.5 onwards -even my Debian Sarge's 2.1.30 version has support for it- ).

The trick seems to be using PHP's ldap_set_option() with option LDAP_OPT_SERVER_CONTROLS, using the Paged Results OID (1.2.840.113556.1.4.319) and the desired number of results as the value (using code similar to example 2 at http://www.php.net/manual/en/function.ldap-set-option.php).

I haven't tested anything of this at all, but the code reading suggests it should work.

Saludos. Iñaki.

In reply to Iñaki Arenaza

Re: Populating Moodle users via Active Directory (LDAP)

by Martín Langhoff -
Interesting! OpenLDAP definitely supports it. PHP's ldap_search() has the sizelimit parameter, but it's lacking a means to indicate offset.

Paged results require that we have both $offset and $limit, so we can fetch the 1st page, and then the 2nd, 3rd, etc.

Is there an ldap_set_option() option to say 'offset 100'? Can you post a code snippet that grabs 100 entries at a time, and can go like that through a large resultset?
In reply to Martín Langhoff

Re: Populating Moodle users via Active Directory (LDAP)

by Iñaki Arenaza -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
I'm affraid my previous analysis of PHP's LDAP code was incomplete. Even if we can set the paged results server option [using ldap_set_option()], we don't have a way to get the values associated with that same option using ldap_get_option() (the module doesn't implement this option, as well as a few others).

The way paged results work is described in RFC 2696. You send a special control request along with your query. That control request includes a "size" (an integer value) and a "cookie" (an octect string, initially sent empty from the client). This is what we set using ldap_set_option() with LDAP_OPT_SERVER_CONTROLS.

The server includes a similar control request in its reply with the cookie value filled in. You have to read the cookie to see if it's empty or not. If the cookie is empty, there are no more results (this was the last page of results). Otherwise, you process these results and send the exact same query with the cookie value you have just read (using a control request just like the first time). The server uses the cookie to track "continuation requests", and sends you the next page of results instead of the first ones.

The problem is we can't get the value of the cookie (or at least I can't see how, since ldap_get_option() doesn't support getting LDAP_OPT_SERVER_CONTROLS neither in PHP 4.3.11 nor 5.0.4).

So I think we are back to square number 1...

Saludos. Iñaki.
In reply to Iñaki Arenaza

Re: Populating Moodle users via Active Directory (LDAP)

by Iñaki Arenaza -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
> The problem is we can't get the value of the cookie (or at least I
> can't see how, since ldap_get_option() doesn't support getting
> LDAP_OPT_SERVER_CONTROLS neither in PHP 4.3.11 nor 5.0.4).

I have digged a little bit more (even if I sound like an LDAP programming expert, this is the first time I do LDAP programming at all smile, and ldap_get_option() is not the way to go. The (response) control requests the server sends back are not stored in our LDAP_OPT_SERVER_CONTROLS data structure (i.e., they don't update it).

These control requests are attached to the responses the server sends back. So we really need to get them from the result response. There is a LDAP function called ldap_parse_result() [see RFC 1823] that does exactly this. PHP's ldap_parse_result() is a wrapper around this function but, I don't know why, the last parameter (serverctrlsp, ¡which is what we really need!) is not available via PHP.

So I have developped and tested a small patch (attached to this message) against PHP 4.3.10 (Debian Sarge's version) LDAP module that provides this value (serversctls) as an array of controls, using the same format we need to use PHP's ldap_set_option() later. If anyone wants to try it out, I can make patches against newer versions of PHP.

But this isn't the end of the story. These controls extensions (Paged Results) have to specify the page size and cookie value as a BER-encoded ASN.1 sequence (the elements of the sequence are described in RFC2696 and ASN.1 BER encondig is described in ITU's X.690 standard). So all we need is a couple of functions to BER-encode/decode those values to/from the control extensions (ideally PHP people should make wrapper functions around OpenLDAP libraries' existing routines).

In order to test my patch (without having to code the BER functions), I have hand-coded the values, looked at what I get back in the control extension from a W2003 AD server, "patched" the returned control extension (to reuse all the BER encoding, without having to do it again manually) and sent the query again with the patched control extension. Guess what? I just works wink

This is the php code I have used to test it all this (really a pice of crap, specially crafted for W2003 AD responses, but I can't do it better without the BER functions):
<?php

define ('PAGE_SIZE', 100);
define ('LDAP_HOST', 'somehost.mydomain.com');
define ('LDAP_USER', 'CN=bind-user,OU=my-users,DC=mydomain,DC=com');
define ('LDAP_PWD', 'bind-user-password');

// CAUTION:
//
// All error checking skipped. This is just sample code
// specially crafted for W2000/W2003 A.D. servers
//

$l = ldap_connect(LDAP_HOST);
$PageControl = array(
array(
'oid' => '1.2.840.113556.1.4.319',
'iscritical' => true,
'value' => sprintf ("%c%c%c%c%c%c%c",
48, 5, 2, 1, PAGE_SIZE, 4, 0)
)
);

ldap_set_option($l,LDAP_OPT_PROTOCOL_VERSION,3);
ldap_bind($l,LDAP_USER,LDAP_PWD);

$continue = true;
while ($continue) {
ldap_set_option($l, LDAP_OPT_SERVER_CONTROLS,$PageControl);
$sr = ldap_search($l, 'OU=some-ou,DC=mydomain,DC=com',
'cn=*', array('sAMAccountName'),
null, null, null, null);
ldap_parse_result ($l, $sr, &$errcode, &$matcheddn,
&$errmsg, &$referrals, &$serverctrls);
if (isset($serverctrls)) {
foreach ($serverctrls as $i) {
if ($i["oid"] == '1.2.840.113556.1.4.319') {
$i["value"]{8} = chr(PAGE_SIZE);
$i["iscritical"] = true;
$PageControl = array();
$PageControl[] = $i;
break;
}
}
}

$info = ldap_get_entries($l, $sr);
print "Data for " . $info["count"] . " items returned:\n";
if ($info["count"] < PAGE_SIZE) {
$continue = false;
}

for ($entry = ldap_first_entry ($l,$sr); $entry != false;
$entry = ldap_next_entry($l,$entry)) {
$dn = ldap_get_dn ($l,$entry);
print "$dn \n";
}
print "\n---------------------------------------\n";
}

?>
So you "only" have to:
  • apply my patch and rebuild PHP's ldap module and
  • code the BER-encode/decode functions.
The latter is left as an exercise for the reader wink

Saludos. Iñaki.

Average of ratings: Useful (1)
In reply to Iñaki Arenaza

Re: Populating Moodle users via Active Directory (LDAP)

by Martín Langhoff -
Iñaki,

this is really cool stuff! Molt bon treball! I suspect the PHP guys will be interested in your patch. One catch though: most of the LDAP data passed around is BER-encoded - and the OpenLDAP client libraries include it. Check out 'man lber-decode'.

No need to do it on the PHP side wink
In reply to Martín Langhoff

Re: Populating Moodle users via Active Directory (LDAP)

by Iñaki Arenaza -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
I suspect the PHP guys will be interested in your patch.

I have opened a bug in PHP (http://bugs.php.net/bug.php?id=34492) with the patch. In case anyone is interested in this going into PHP anytime soon, they better vote for it wink

Saludos. Iñaki.
In reply to Iñaki Arenaza

Re: Populating Moodle users via Active Directory (LDAP)

by Martín Langhoff -
Done my part wink

Do you think you can get it to do the BER-decoding before the data gets to the PHP layer? If so, I'll be more than happy to build Debian packages for Sarge (i368, amd64, powerpc) of the modified PHP so we can start using it...

Saludos!
In reply to Martín Langhoff

Re: Populating Moodle users via Active Directory (LDAP)

by Iñaki Arenaza -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Do you think you can get it to do the BER-decoding before the data gets to the PHP layer?

I think we should do all the BER encoding/decoding at the PHP layer. Given that there are several control extensions available [1] and that every control extension uses a different set of values in the controlValue field [2], doing this below the PHP layer (inside the LDAP module) means we need to know in advance which control extensions we are going to "recognize" in order to decode the right set of values.

On the other hand, if we do this at the PHP layer, the application knows exactly what it expects and the format of the associated data. It can ignore the control extensions it doesn't "recognize" (or isn't interested in), and just proccess the "interesting" ones.

I think we only need to make wrappers around ber_print and ber_scanf (and hide all the dirty details -like BER elements allocation and such- inside the ldap module) to make this happen at the PHP layer.

Saludos. Iñaki.

[1] There are several available now, but nothing in the standard prevents the creation of new ones.

[2] In fact RFC 2251, section 4.1.12, says this field's format (number of values and their type) is defined by each control extension.
In reply to Iñaki Arenaza

Re: Populating Moodle users via Active Directory (LDAP)

by Martín Langhoff -
Then you're thinking of exposing ber_print/ber_scanf to PHP so we don't have to rewrite them in PHP? That's be more than enough for me...
In reply to Martín Langhoff

Re: Populating Moodle users via Active Directory (LDAP)

by Iñaki Arenaza -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Then you're thinking of exposing ber_print/ber_scanf to PHP so we don't have to rewrite them in PHP?

I think that's the most sensible thing in the long run.

Saludos. Iñaki.
In reply to Iñaki Arenaza

Re: Populating Moodle users via Active Directory (LDAP)

by Iñaki Arenaza -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
It's been a while since my last post on the subject because I've been really busy (the first semester has just begun here).

But I have been able to work a little bit with the code and here is attached a patch against Debian Sarges PHP4 package (php4-4.3.10). It's beta quality code so don't relay on it for production by now wink

I have made several successful tests against my W2K3 AD with different page  sizes, but haven't had the chance to test it with an OpenLDAP server yet.

I think there are no obvious bugs in the code (i.e., pointers going astray, memory leaks, etc.) but this is the first time I use the Zend API, so I could be missing something.

Finally the documentation for the two new functions [ldap_ber_printf(), ldap_ber_scanf()] is missing, but it should be fairly obvious how to use them looking at the ber_scanf()/ber_printf() manpages.

There are a couple of encondings that are not supported so far ('v' and 'V') and two OpenLDAP extensions to the standard draft that are not implemented. The reason is a) we don't need it for paged results at all, b) they are a little bit trickier than the rest, and I wanted to push the code out ASAP for you to test it.

Here is sample PHP code to use the new functions to get paged results working:

=========================================================
 
<?php

define ('PAGE_SIZE', 500);
define ('LDAP_HOST', 'myserver.mydomain.com' );
define ('LDAP_USER', 'cn=myuser,ou=myusers,dc=mydomain,dc=com' );
define ('LDAP_PWD', 'mypassword' );

$cookie = "";

$l = ldap_connect(LDAP_HOST);
ldap_set_option($l,LDAP_OPT_PROTOCOL_VERSION,3);
ldap_bind($l,LDAP_USER,LDAP_PWD);

$continue = true;
while ($continue) {
$PageControl = array(
array(
'oid' =>'1.2.840.113556.1.4.319',
'iscritical' => true,
'value' => ldap_ber_printf("{iO}",
PAGE_SIZE, $cookie)
)
);
ldap_set_option($l, LDAP_OPT_SERVER_CONTROLS, $PageControl);

$sr = ldap_search($l,'ou=myusers,dc=mydomain,dc=com',
'cn=*', array('sAMAccountName'),
null, null, null, null);

ldap_parse_result ($l, $sr, &$errcode, &$matcheddn,
&$errmsg, &$referrals, &$serverctrls);

if (isset($serverctrls)) {
foreach ($serverctrls as $i) {
if ($i["oid"] == '1.2.840.113556.1.4.319') {
ldap_ber_scanf($i["value"], "{iO}",
&$pagesize, &$cookie);
break;
}
}
}
$info = ldap_get_entries($l, $sr);
print "Data for " . $info["count"] . " items returned:\n";
for ($entry = ldap_first_entry ($l,$sr); $entry != false;
$entry = ldap_next_entry($l,$entry)) {
$dn = ldap_get_dn ($l,$entry);
print "$dn \n";
}
print "\n---------------------------------------\n\n";
if ($cookie == "") {
$continue = false;
}
}

?>

=========================================================
Any feedback is welcome.

Saludos. Iñaki.

In reply to Iñaki Arenaza

Re: Populating Moodle users via Active Directory (LDAP)

by Iñaki Arenaza -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
I have just uploaded diffs against CVS versions of PHP-4.4.0, PHP-5.0 and PHP-5.1, current as of today to:

http://www.eteo.mondragon.edu/descargas/php-ldap/

in case anybody is interested in testing it.

Saludos. Iñaki.
In reply to Iñaki Arenaza

Re: Populating Moodle users via Active Directory (LDAP)

by Sean Toman -

I am running moodle 1.9.6 on php 5.2.12

As regards user synchronisation, I am experiencing the AD limit problem when running ..../moodle/auth/ldap/auth_ldap_sync_users.php.

As per the notes above, I tried the following

- updated php 5.2.12 with the path from the web site above and

- changed ..../moodle/auth/ldap/auth.php based upon the PHP paging code above, which uses ldap_ber_printf().

This did not work so I tried the following

- changed ..../moodle/auth/ldap/auth.php based upon the older PHP paging code above, which does not uses ldap_ber_printf().

This has more success in that it successfully retrieves more than 1000 entries from AD if required by retrieving a 1000 at a time, in each page.

However, later in the processing, it will connect to AD again to get more detailed information on each entry and fails to get information including the username.  I am guessing the paging code that has been inserted into auth.php has an adverse ripple effect on the retrieval of the detailed information.

The changed auth.php is attached. 

Log

Connecting to ldap...
        + 1000 users
entry_count >1000<
        + 1000 users
entry_count >1000<
        + 231 users
entry_count >231<
Got 2231 records from LDAP

No updates to be done
No updates to be done
User entries to add: 2231

Notice: Undefined property: stdClass::$username in /wwwroot/htdocs/moodle/auth/ldap/auth.php on line 913

Notice: Undefined property: stdClass::$username in /wwwroot/htdocs/moodle/auth/ldap/auth.php on line 914
        Inserted user  id 30964

Notice: Trying to get property of non-object in /wwwroot/htdocs/moodle/auth/ldap/auth.php on line 904

Notice: Trying to get property of non-object in /wwwroot/htdocs/moodle/auth/ldap/auth.php on line 904

Notice: Undefined property: stdClass::$username in /wwwroot/htdocs/moodle/auth/ldap/auth.php on line 913

Notice: Undefined property: stdClass::$username in /wwwroot/htdocs/moodle/auth/ldap/auth.php on line 914
<div class="notifytiny" style="text-align:center">Duplicate entry '1-' for key 2<br /><br />INSERT INTO mdl_user ( AUTH, CONFIRMED, MNETHOSTID, USERNAME, LANG ) VALUES ( 'ldap', 1, 1, '', 'en_utf8' )<ul style="text-align:left"><li>line 1554 of lib/dmllib.php: call to debugging()</li><li>line 922 of auth/ldap/auth.php: call to insert_record()</li><li>line 44 of auth/ldap/auth_ldap_sync_users.php: call to auth_plugin_ldap-&gt;sync_users()</li></ul></div>
        Error inserting user

Any help - much appreciated? Does anyone have an auth.php which successfully retrieves more than 1000 entries from AD and inserts them into mySQL?

Thanks

In reply to Iñaki Arenaza

Re: Populating Moodle users via Active Directory (LDAP)

by Dale B -
Iñaki,

I am trying to do a similar thing, but I am running into slightly different problem. Your code has so far made it so I can page query an OU for its DNs, but with ActiveDirectory, at least the way we have it, the members of a group are listed as a multi-attribute called member in the group object. Wow - that was clear, anyway, I can do an ldapsearch on a debian box, that queries a W2K3 DC, that looks sort of like this -

ldapsearch -x -b ou=mygroups,ou=myusers,dc=mydomain,dc=edu -D "cn=myquery-acct,ou=myusers,dc=mydomain,dc=edu" -w mypassword -h w2k3-pdc.mydomain.edu "(&(objectCategory=group)(name=students))" member

and it spits out the first page of a query:
--------------------------------------------------------------------------------------------

# extended LDIF
#
# LDAPv3
# base <ou=mygroups,ou=myusers,dc=alfredstate,dc=edu> with scope sub
# filter: (&(objectCategory=group)(name=mystudents))
# requesting: member
#

# student, mygroups, myusers, mydomain.edu
dn: CN=mystudents,OU=mygroups,OU=myusers,DC=mydomain,DC=edu
member;range=0-1499: CN=Riviera Doris D,OU=mystudents,OU=myusers,DC=mydomain,DC=edu
member;range=0-1499: CN=Rhudel Willhem K,OU=mystudents,OU=myusers,DC=mydomain,DC=edu
.member;range=0-1499: CN=Rundel Alan J,OU=mystudents,OU=myusers,DC=mydomain,DC=edu
...

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

--------------------------------------------------------------------------------------------
the dn being searched is dn: CN=mystudents,OU=mygroups,OU=myusers,DC=mydomain,DC=edu
and the multi-attribute is member. So, using your code, I change the line from

$sr = ldap_search($l,'ou=mygroups,ou=myusers,dc=mydomain,dc=edu',
'cn=*', array('sAMAccountName'),
null, null, null, null);

to:

$sr = ldap_search($l,'ou=mygroups,ou=myusers,dc=mydomain,dc=edu',
'(&(objectCategory=group) (name=mystudents))', array('member'),
null, null, null, null);


and the webpage puts out:

Data for 1 item returned: CN=mystudents,OU=mygroups,OU=myusers,DC=mydomain,DC=edu
--------------------------------------------------

I would have expected a bunch of member DNs instead. Do you know how
I would search for the multi-attribute using your code? (Some special LBER or something?) Thanks for any ideas!

Dale B

In reply to Dale B

Re: Populating Moodle users via Active Directory (LDAP)

by Iñaki Arenaza -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

Sorry for the delay sad

In fact, what you are getting is exactly what you asked for: the entry for the group. As you rightly say, members are attributes of that entry. So once you get the entry from LDAP, you just need to process that attribute. You can use ldap_get_values() to extract the values of a given attribute. Just add something like this after the line that prints the $dn:

echo "<br />";
$members = ldap_get_values ($l, $entry, 'member');
for ($i = 0; $i < $members['count']; $i++) {
    echo "member: " . $members[$i] . "<br />";
}

Saludos. Iñaki.

In reply to Iñaki Arenaza

Re: Populating Moodle users via Active Directory (LDAP)

by Mike Edwards -
I don't have any real right to the AD, its managed by another group.  Getting any sort of changes is close to the Spanish Inquisistion.

That's some good info though.  I might convert the script to something else and see if I can get it to work...

Mike
In reply to Martín Langhoff

Re: Populating Moodle users via Active Directory (LDAP)

by Samuli Karevaara -
How about "populating new accounts created to AD before they log in"? Is this possible? (willing to change code smile )
In reply to Samuli Karevaara

Re: Populating Moodle users via Active Directory (LDAP)

by Martín Langhoff -
> How about "populating new accounts created to AD before they
> log in"? Is this possible?

This is better done _outside_ of Moodle, by a separate script (of the kind of accessory scripts we put in cvs:/contrib ) . I'll probably put together a Perl (or PHP) script that reads mdl_user and outputs an LDIF that you can feed to AD or OpenLDAP.

Actually, it's likely to happen before the end of the year, I have some Moodle setups that need an LDAP backend.
In reply to Martín Langhoff

Re: Populating Moodle users via Active Directory (LDAP)

by Samuli Karevaara -
I meant "populate the Moodle DB with new accounts from AD, before the user logs in Moodle".

We are populating the AD with separate scripts from our student management systems, but the users are seen in Moodle only after they have logged in once.

We'd like to be able to put them on courses et cetera even before they have logged in Moodle. Now I did some small bits of code to convert LDIF to a CSV file that Moodle eats, and pre-filled the accounts that way. Running in to the size limit also, though, so I'm running a lot of LDIF files out of the AD.
In reply to Samuli Karevaara

Re: Populating Moodle users via Active Directory (LDAP)

by Martín Langhoff -
> I meant "populate the Moodle DB with new accounts from AD,
> before the user logs in Moodle".

That's already possible. There is a script inside auth/ldap and another inside enrol/ldap. We run both of them around midnight. No messing around w CSV files.
In reply to Martín Langhoff

Re: Populating Moodle users via Active Directory (LDAP)

by Samuli Karevaara -
You mean then "sync LDAP users" bit? Thanks, I didn't know that it also creates the missing users, thought it only updates data for the already known ones.

You use an LDAP with no (or larger) max query size than 1000? We have AD and some contexts with more than 1000 users so something else still must be hacked in. Maybe some other parameter to iterate to than the contexts, to break it to pieces smaller than 1000...
In reply to Samuli Karevaara

Re: Populating Moodle users via Active Directory (LDAP)

by Mike Tupker -

I've been trying to get the auth_ldap_sync_users.php script to work and every time I try and run it in a browser I get a blank screen. I saw something saying that it should be run from a command line but it doesn't seem to do anything. I'm running moodle on server 2k3 with php5. Does anyone know what the correct command line sytax is to run auth_ldap_sync_users.php? Thanks.

In reply to Mike Edwards

Re: Populating Moodle users via Active Directory (LDAP)

by arvind grover -
Mike wrote:
How can I limit this access to members of a central group? Like; cn=moodleAccounts,ou=myOU,dc=some_ad,dc=some_school,dc=edu

If I understand your question correctly, it is easy. In the Moodle >> Administration >> Users >> Authentication section, only add those groups to the
ldap_contexts section. The authentication module should then only look in those OU's for users, and if it doesn't find them, it will not authenticate, and not create a Moodle account.

Is that what you are asking?