Skip to content

Commit

Permalink
mod_auth_ldap, non-anon binding and openxchange support
Browse files Browse the repository at this point in the history
The attached patch builds on your work in the following ways:
1. adds support for non-anonymous binding.  Leaving the extra config
variables empty results in an anonymous bind.  I haven't fully tested
this (I cannot test the anonymous case), but any problems should be
apparent immediately.

2. adds support for httpd authentication.  I use mod_auth_ldap to
authenticate access to the site.  This prevents the user having to login
twice.

3. adds support for parts of the openxchange schema
(http://www.openxchange.org). Only the parts I found useful are added.
The openxchange.schema is not included as the user that enables this is
expected to have already installed openxchange.

darcs-hash:20060117111459-bb1f7-cc6f1f6e943f5c6ffa8f393f68c32500505dae67.gz
  • Loading branch information
Daniel Tarbuck committed Jan 17, 2006
1 parent c40429e commit 77d53c7
Show file tree
Hide file tree
Showing 13 changed files with 380 additions and 5 deletions.
7 changes: 5 additions & 2 deletions README
Expand Up @@ -2,7 +2,7 @@


LDAPab is a webbased address book for small companies. It features a public LDAPab is a webbased address book for small companies. It features a public
address book which is writable for all company staff and a personal address address book which is writable for all company staff and a personal address
book for each staff member. LDAPab require an already setup LDAP server to book for each staff member. LDAPab requires an already setup LDAP server to
authenticate users. authenticate users.


=== REQUIREMENTS === === REQUIREMENTS ===
Expand All @@ -18,11 +18,14 @@ with LDAP support (compiled in or as extension)


Copy the contents of the .tgz file to a directory below your webserver document Copy the contents of the .tgz file to a directory below your webserver document
root. Make sure the webserver is able to write to the cache directory which is root. Make sure the webserver is able to write to the cache directory which is
used for the template engines cache files. A 'chmod 777 cache' will do. used for the template engine's cache files. A 'chmod 777 cache' will do.


Open the config.php file in your favourite editor and edit the options Open the config.php file in your favourite editor and edit the options
according to your needs. Some knowlege about LDAP may come in handy. according to your needs. Some knowlege about LDAP may come in handy.


If HTTP auth is wanted have a look at the provided _htaccess file, edit it as
needed and rename it back to .htaccess

=== SETUP THE LDAP SERVER === === SETUP THE LDAP SERVER ===


The following only describes what to do for open-ldap 2.0! If you use any The following only describes what to do for open-ldap 2.0! If you use any
Expand Down
27 changes: 27 additions & 0 deletions _htaccess
@@ -0,0 +1,27 @@
#
# Example .htaccess to use with mod_authldap
#

AuthName "LDAPab"
AuthType basic

AuthLDAPURL "ldap://ldap/ou=people,o=cosmocode,c=de?uid?one"

### LDAP Bind information
#AuthLDAPBindDN cn=NonAnon,o=cosmocode,c=de
#AuthLDAPBindPassword secret

### For LDAP group authentication
#AuthLDAPGroupAttribute memberUid
#AuthLDAPGroupAttributeIsDN off
#require group cn=Users,ou=Groups,o=cosmocode,c=de

### Authorize users individually
#require user myusername

### Authorize any authenticated user
require valid-user

### Require SSL for access
#SSLRequireSSL

19 changes: 19 additions & 0 deletions config.php
Expand Up @@ -3,6 +3,9 @@
// Which LDAP Server to use? // Which LDAP Server to use?
$conf[ldapserver] = 'ldap'; $conf[ldapserver] = 'ldap';


// Which LDAP Port Server to use? (389 is standard, 636 for ssl)
$conf[ldapport] = 389;

// What is the root dn on this Server? // What is the root dn on this Server?
$conf[ldaprootdn] = 'o=cosmocode, c=de'; $conf[ldaprootdn] = 'o=cosmocode, c=de';


Expand All @@ -12,6 +15,10 @@
// How to match users? %u is replaced by the given login // How to match users? %u is replaced by the given login
$conf[userfilter] = '(&(uid=%u)(objectClass=posixAccount))'; $conf[userfilter] = '(&(uid=%u)(objectClass=posixAccount))';


// Use these values to bind to the ldap directory when not logged in (leave blank for anonymous bind)
$conf[anonbinddn] = '';
$conf[anonbindpw] = '';

// Which language to use (see lang directory) // Which language to use (see lang directory)
$conf[lang] = 'de'; $conf[lang] = 'de';


Expand All @@ -21,6 +28,17 @@
// Where to store private contacts (relative to $conf[usertree]) // Where to store private contacts (relative to $conf[usertree])
$conf[privatebook] = 'ou=contacts'; $conf[privatebook] = 'ou=contacts';


// Should the additional schema ldapab.schema be used? (0|1)
// Note: openxchange and extended are currently exclusive, do not use both at the same time!
$conf[extended] = 0;

// Should we use some parts of the openxchange.schema? (0|1)
// Note: openxchange and extended are currently exclusive, do not use both at the same time!
$conf[openxchange] = 1;

// Should we try to login using the username and password provided by httpd? (0|1)
$conf[httpd_auth] = 1;

// Should the additional schema ldapab.schema be used? (0|1) // Should the additional schema ldapab.schema be used? (0|1)
$conf[extended] = 1; $conf[extended] = 1;


Expand All @@ -31,4 +49,5 @@


// Force recompilation of smarty templates? // Force recompilation of smarty templates?
$conf[smartycompile] = 0; $conf[smartycompile] = 0;

?> ?>
7 changes: 7 additions & 0 deletions entry.php
Expand Up @@ -41,6 +41,9 @@
tpl_std(); tpl_std();
tpl_orgs(); tpl_orgs();
tpl_markers(); tpl_markers();
tpl_categories();
tpl_timezone();
tpl_country();
//display templates //display templates
if($_REQUEST[mode]=='vcf'){ if($_REQUEST[mode]=='vcf'){
$entry = $smarty->get_template_vars('entry'); $entry = $smarty->get_template_vars('entry');
Expand Down Expand Up @@ -132,6 +135,10 @@ function _saveData(){
if($conf[extended]){ if($conf[extended]){
ldap_store_objectclasses($dn,array('inetOrgPerson','contactPerson')); ldap_store_objectclasses($dn,array('inetOrgPerson','contactPerson'));
} }
// in openxchange mode we have to make sure the right classes are set
if ($conf[openxchange]){
ldap_store_objectclasses($dn,array('inetOrgPerson','OXUserObject'));
}
//modify entry (touches only our attributes) //modify entry (touches only our attributes)
foreach (array_keys($entries) as $key){ foreach (array_keys($entries) as $key){
if($key == 'dn'){ if($key == 'dn'){
Expand Down
23 changes: 21 additions & 2 deletions functions.php
Expand Up @@ -13,13 +13,17 @@ function smarty_std(){
* If it fails it redirects to login.php * If it fails it redirects to login.php
*/ */
function ldap_login(){ function ldap_login(){
global $conf;
if(!empty($_SESSION[ldapab][username])){ if(!empty($_SESSION[ldapab][username])){
//existing session! Check if valid //existing session! Check if valid
if($_COOKIE[ldapabconid] != $_SESSION[ldapab][conid]){ if($_COOKIE[ldapabconid] != $_SESSION[ldapab][conid]){
//session hijacking detected //session hijacking detected
header('Location: login.php?username='); header('Location: login.php?username=');
exit; exit;
} }
} elseif ($conf[httpd_auth] && !empty($_SERVER[PHP_AUTH_USER])) {
$_SESSION[ldapab][username] = $_SERVER[PHP_AUTH_USER];
$_SESSION[ldapab][password] = $_SERVER[PHP_AUTH_PW];
} }


if(!do_ldap_bind($_SESSION[ldapab][username], if(!do_ldap_bind($_SESSION[ldapab][username],
Expand All @@ -39,15 +43,16 @@ function do_ldap_bind($user,$pass,$dn=""){


//create global connection to LDAP if nessessary //create global connection to LDAP if nessessary
if(!$LDAP_CON){ if(!$LDAP_CON){
$LDAP_CON = ldap_connect($conf[ldapserver]); $LDAP_CON = ldap_connect($conf[ldapserver],$conf[ldapport]);
if(!$LDAP_CON){ if(!$LDAP_CON){
die("couldn't connect to LDAP server"); die("couldn't connect to LDAP server");
} }
} }


if(empty($dn)){ if(empty($dn)){
//anonymous bind to lookup users //anonymous bind to lookup users
if(!ldap_bind($LDAP_CON)){ //blank binddn or blank bindpw will result in anonymous bind
if(!ldap_bind($LDAP_CON,$conf[anonbinddn],$conf[anonbindpw])){
die("can not bind anonymously"); die("can not bind anonymously");
} }


Expand Down Expand Up @@ -152,6 +157,17 @@ function namedentries($flip=false){
if($conf[extended]){ if($conf[extended]){
$entries[anniversary] = 'anniversary'; $entries[anniversary] = 'anniversary';
} }
if($conf[openxchange]){
$entries[mailDomain] = 'domain';
$entries[userCountry] = 'country';
$entries[birthDay] = 'birthday';
$entries[IPPhone] = 'ipphone';
$entries[OXUserCategories] = 'categories';
$entries[OXUserInstantMessenger] = 'instantmessenger';
$entries[OXTimeZone] = 'timezone';
$entries[OXUserPosition] = 'position';
$entries[relClientCert] = 'certificate';
}


if($flip){ if($flip){
$entries = array_reverse($entries); $entries = array_reverse($entries);
Expand Down Expand Up @@ -190,6 +206,9 @@ function prepare_ldap_entry($in){
if($conf[extended]){ if($conf[extended]){
$out[objectclass][] = 'contactPerson'; $out[objectclass][] = 'contactPerson';
} }
if($conf[openxchange]){
$out[objectclass][] = 'OXUserObject';
}


utf8_encode_array($out); utf8_encode_array($out);


Expand Down
7 changes: 7 additions & 0 deletions index.php
Expand Up @@ -42,6 +42,9 @@
//prepare templates //prepare templates
tpl_std(); tpl_std();
tpl_markers(); tpl_markers();
tpl_categories();
tpl_timezone();
tpl_country();
$smarty->assign('list',$list); $smarty->assign('list',$list);
$smarty->assign('filter',$_REQUEST['filter']); $smarty->assign('filter',$_REQUEST['filter']);
$smarty->assign('marker',$_REQUEST['marker']); $smarty->assign('marker',$_REQUEST['marker']);
Expand Down Expand Up @@ -84,12 +87,16 @@ function _makeldapfilter(){
$search = $_REQUEST['search']; $search = $_REQUEST['search'];
$org = $_REQUEST['org']; $org = $_REQUEST['org'];
$marker = $_REQUEST['marker']; $marker = $_REQUEST['marker'];
$categories = $_REQUEST['categories'];
$_SESSION[ldapab][filter] = $filter; $_SESSION[ldapab][filter] = $filter;
if(empty($filter)) $filter='a'; if(empty($filter)) $filter='a';


if(!empty($marker)){ if(!empty($marker)){
$marker = utf8_encode($marker); $marker = utf8_encode($marker);
$ldapfilter = "(&(objectClass=contactPerson)(marker=$marker))"; $ldapfilter = "(&(objectClass=contactPerson)(marker=$marker))";
}elseif(!empty($categories)){
$categories = utf8_encode($categories);
$ldapfilter = "(&(objectClass=OXUserObject)(OXUserCategories=$categories))";
}elseif(!empty($search)){ }elseif(!empty($search)){
$search = trim($search); $search = trim($search);
$words=preg_split('/\s+/',$search); $words=preg_split('/\s+/',$search);
Expand Down
14 changes: 13 additions & 1 deletion lang/en.php
Expand Up @@ -2,7 +2,7 @@


$lang[ldapab] = 'The LDAP address book'; $lang[ldapab] = 'The LDAP address book';


$lang[name] = 'Name'; $lang[name] = 'Last Name';
$lang[givenname] = 'First Name'; $lang[givenname] = 'First Name';
$lang[title] = 'Title'; $lang[title] = 'Title';
$lang[organization] = 'Company'; $lang[organization] = 'Company';
Expand Down Expand Up @@ -66,4 +66,16 @@


$lang[err_noentries] = 'No entries'; $lang[err_noentries] = 'No entries';
$lang[err_ldap] = 'The LDAP server returned the following errors'; $lang[err_ldap] = 'The LDAP server returned the following errors';

$lang[openxchange] = 'Xchange Information';
$lang[moreopenxchange] = 'Xchange Information Cont\'d';
$lang[instantmessenger] = 'Inst Msg';
$lang[categories] = 'Categories';
$lang[birthday] = 'Birthday';
$lang[domain] = 'Mail Domain';
$lang[country] = 'Country';
$lang[certificate] = 'x.509 Cert';
$lang[timezone] = 'Time Zone';
$lang[position] = 'Position';
$lang[ipphone] = 'IP Phone';
?> ?>
121 changes: 121 additions & 0 deletions template.php
Expand Up @@ -58,6 +58,10 @@ function tpl_entry($in){
//handle marker special in extended mode //handle marker special in extended mode
$out['marker'] = $in['marker']; $out['marker'] = $in['marker'];
} }
if ($conf[openxchange]){
//handle categories special in openxchange mode
$out['categories'] = $in['OXUserCategories'];
}


//decode array //decode array
utf8_decode_array($out); utf8_decode_array($out);
Expand Down Expand Up @@ -160,4 +164,121 @@ function tpl_orgs(){
$smarty->assign('orgs',$orgs); $smarty->assign('orgs',$orgs);
} }


/**
* assigns all categories to the template
*/
function tpl_categories(){
global $conf;
global $LDAP_CON;
global $smarty;

if(!$conf[openxchange]) return;

$categories = array();

$sr = ldap_list($LDAP_CON,$conf[publicbook],"ObjectClass=OXUserObject",array("OXUserCategories"));
$result1 = ldap_get_binentries($LDAP_CON, $sr);
//check users private addressbook
if(!empty($_SESSION[ldapab][binddn])){
$sr = @ldap_list($LDAP_CON,
$conf[privatebook].','.$_SESSION[ldapab][binddn],
"ObjectClass=OXUserObject",array("OXUserCategories"));
$result2 = ldap_get_binentries($LDAP_CON, $sr);
}
$result = array_merge($result1,$result2);

if(count($result)){
foreach ($result as $entry){
if(count($entry['OXUserCategories'])){
foreach($entry['OXUserCategories'] as $category){
array_push($categories, $category);
}
}
}
}
$categories = array_unique($categories);
sort($categories,SORT_STRING);

utf8_decode_array($categories);
$smarty->assign('categories',$categories);
}

/**
* assigns all timezones to the template
*/
function tpl_timezone(){
global $conf;
global $LDAP_CON;
global $smarty;

if(!$conf[openxchange]) return;

$timezone = array();

$sr = ldap_list($LDAP_CON,$conf[publicbook],"ObjectClass=OXUserObject",array("OXTimeZone"));
$result1 = ldap_get_binentries($LDAP_CON, $sr);
//check users private addressbook
if(!empty($_SESSION[ldapab][binddn])){
$sr = @ldap_list($LDAP_CON,
$conf[privatebook].','.$_SESSION[ldapab][binddn],
"ObjectClass=OXUserObject",array("OXTimeZone"));
$result2 = ldap_get_binentries($LDAP_CON, $sr);
}
$result = array_merge($result1,$result2);

if(count($result)){
foreach ($result as $entry){
if(count($entry['OXTimeZone'])){
foreach($entry['OXTimeZone'] as $tz){
array_push($timezone, $tz);
}
}
}
}
$timezone = array_unique($timezone);
sort($timezone,SORT_STRING);

utf8_decode_array($timezone);
$smarty->assign('timezone',$timezone);
}

/**
* assigns all countries to the template
*/
function tpl_country(){
global $conf;
global $LDAP_CON;
global $smarty;

if(!$conf[openxchange]) return;

$country = array();

$sr = ldap_list($LDAP_CON,$conf[publicbook],"ObjectClass=OXUserObject",array("userCountry"));
$result1 = ldap_get_binentries($LDAP_CON, $sr);
//check users private addressbook
if(!empty($_SESSION[ldapab][binddn])){
$sr = @ldap_list($LDAP_CON,
$conf[privatebook].','.$_SESSION[ldapab][binddn],
"ObjectClass=OXUserObject",array("userCountry"));
$result2 = ldap_get_binentries($LDAP_CON, $sr);
}
$result = array_merge($result1,$result2);

if(count($result)){
foreach ($result as $entry){
if(count($entry['userCountry'])){
foreach($entry['userCountry'] as $c){
array_push($country, $c);
}
}
}
}
$country = array_unique($country);
sort($country,SORT_STRING);

utf8_decode_array($country);
$smarty->assign('country',$country);
}

?> ?>
3 changes: 3 additions & 0 deletions templates/entry_edit.tpl
Expand Up @@ -169,6 +169,9 @@
</td> </td>
</tr> </tr>
{/if} {/if}
{if $conf.openxchange}
{include file="openxchange_edit.tpl"}
{/if}
<tr> <tr>
<td colspan="2" align="center"><br><input type="submit" class="input" value="{$lang.submit}"></td> <td colspan="2" align="center"><br><input type="submit" class="input" value="{$lang.submit}"></td>
</tr> </tr>
Expand Down
3 changes: 3 additions & 0 deletions templates/entry_show.tpl
Expand Up @@ -116,5 +116,8 @@
</td> </td>
</tr> </tr>
</table> </table>
{if $conf.openxchange}
{include file="openxchange_show.tpl"}
{/if}
<br><br><br> <br><br><br>


0 comments on commit 77d53c7

Please sign in to comment.