What we need
Current version of Dspace installed on our Web Server works perfectly well, but we are in need of adding some new functionalities to the LDAP Auth mechanism implemented in. In our particular case, it’s necessary to allow users “white-list” and, at the same time, to implement one extra check so as to grant access to a some valid LDAP authenticated user depending on some extended attributes of our LDAP institutional servers.
Implementing the concept of “users white-list” through the LDAP Authtentication mechanism
Dspace is entirely written in Java and JScript. Our source code file involving LDAP Authentication behaviour is src/org/dspace/app/webui/servlet/LDAPServlet.java. Reading this file carefully, we can found a method called ldapAuthenticate(), in charge of connecting to the LDAP servers configured in DSpace, and validating the user. The idea is so simple: in case of being connected to the LDAP tree structure, it’s supossed the user has valid credentials so that he can be entering inside Dspace webpage, returning a “true” value inside this method. Otherwise, this method will return “false”, and the access will be denied to the user.
Thus, we needed to add some code right inside this method, just after passing the LDAP binding process correctly, in order to open an external file – our white-list configuration file, in fact -, and iterate over all its entries, looking for the validated user through LDAP tree. In case of finding this user in the white-list file, we return true. Otherwise, we can go on with the last part of authentication mechanism, that is: checking for an additional LDAP attributes. In our case, the “unitCode” field, see below.
All the code added in order to implement the white-list is shown below:
... 65 // TCG: add support for FileReader 66 import java.io.*; ... 82 // TCG: the white-file-list: 83 private static final String WHITE_FILE_LIST = "/etc/dspace-white-list.cfg"; ... 376 //TCG: check white-list : 377 log.info(LogManager.getHeader(context, 378 "TCG: ldap_white_list_check", "type=white-list, got=" + netid)); 379 try{ 380 381 boolean found = false; /* By default, not found */ 382 String curEntry=""; /* current user in white-list */ 383 384 // Okay guys, in case of the presence of a white-list-file ... : 385 BufferedReader fl = new BufferedReader(new FileReader(WHITE_FILE_LIST)); 386 /* Look for its name ... */ 387 log.info(LogManager.getHeader(context, 388 "TCG: ldap_white_list_opened", "type=white-list, status=opened")); 389 do{ 390 curEntry = fl.readLine(); 391 log.info(LogManager.getHeader(context, 392 "TCG: ldap_white_list_loop", "type=search,value=" + curEntry )); 393 if(curEntry!=null && netid.compareTo(curEntry)==0){ 394 found=true; 395 log.info(LogManager.getHeader(context, 396 "TCG: ldap_white_list_search", "type=white-list, status=found_white_entry, value= " + curEntry)); 397 break; 398 } 399 }while(curEntry!=null); 400 fl.close(); /* Close the file ... */ 401 if(found)return true; /* Avoid ldap unitcode check if we've found in the white-list ... ... |
As shown in the previous code listing, we hard-coded the filename directly, but it is absolutelly feasible to add some code so as to use a Dspace config directive to choose the path and the name of this file, which could be better than hardcoding it inside this source code file.
Checking an additional LDAP attribute before granting access to the user
In our particular case, we were in need of allowing the access to a valid linked user to the LDAP tree only if he belongs to some numerical codes for the extended LDAP attribute unitCode. This way, the access will be granted or denied, depending on this attribute. In short:
(unitCode = { 720, 721 }) ? Granted : Denied
So as to do so, I added some code in order to get this custom LDAP attribute inside the ldapAuthenticate() method, and then, right after passing the loop inside “white-list” mechanism, a trivial if clause determines if the user belongs to these numerical codes, allowing or denying the access. This code is shown below:
295 // TCG: Read new option in config file por unitCode field: 296 String ldap_unitCode_field = ConfigurationManager.getProperty("ldap.unitCode_field"); 301 //TCG: need unitCode field for matching ! ? 302 matchAttrs.put(new BasicAttribute(ldap_unitCode_field)); ... 304 // TCG: Add new field to receive after query from ldap server: 305 String attlist[] = {ldap_email_field, ldap_givenname_field, ldap_surname_field, ldap_phone_ field, ldap_unitCode_field}; ... 341 // TCG: get the unitCode attribute and store it! 342 if (attlist[4]!=null) 343 { 344 att = atts.get(attlist[4]); 345 if (att != null) ldapunitCode = (String)att.get(); 346 } ... 403 // User not found in white-list ... : 404 log.info(LogManager.getHeader(context, 405 "TCG: ldap_white_list_search", "type=white-list, status=not_found_white_entry, looking_for=" + netid)); 406 407 // Check the unitCode, if needed : 408 log.info(LogManager.getHeader(context, 409 "TCG: ldap_attribute_check", "type=unitCode, got=" + ldapunitCode)); 410 Integer icode = new Integer(ldapunitCode); 411 if(icode.intValue()<720||icode.intValue()>721) return false; ... |
And that’s all.
Applying the changes, compiling and installing the modified Dspace server
It’s a piece of cake. Recompile the sources, copy two files and restart the TOMCAT server:
# ant clean # ant update # /etc/init.d/tomcat5 stop # rm -r /usr/share/tomcat5/webapps/dspace # rm -r /usr/share/tomcat5/webapps/dspace-oai # cp build/* /usr/share/tomcat5/webapps # /etc/init.d/tomcat5 start |
Finally, create a new white-list file and add all users desired by hand:
# touch /etc/dspace-white-list.cfg # echo "user_name.user_surname" >> /etc/dspace-white-list.cfg # echo "new_user.ldap" >> /etc/dspace-white-list.cfg ... |