Using phpQLAdmin with existing LDAP database
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you already have an LDAP database you'd like to administrate
through phpQLAdmin, it is a requirenment that you read README.acl and
FULLY understand the limitations layed out in 'Configuration and layout'
and 'Problematic database layout'.

If you don't (and fully understand this! :), you won't see your database
(or not all of it), no matter HOW you configure it. Also look at
'Configuration in LDAP' below for more about this.


Upgrading
~~~~~~~~~
If you're upgrading from a phpQLAdmin version older than 2.0.13,
then you MUST read the README.upgrade file! It contains important
information that will break your admin interface (phpQLAdmin) if
not fully understood.


LDAP layout independence
~~~~~~~~~~~~~~~~~~~~~~~~
Version 2.0 of phpQLAdmin was (re)designed to be more forgiving on how
the layout of the LDAP database is layed out. It does however dictate
slightly that you follow some kind of 'standard' (if there is such
a thing in the world of LDAP :).


Configuration and layout
~~~~~~~~~~~~~~~~~~~~~~~~
To configure phpQLAdmin, copy the file include/config.inc.CHANGE_ME
to include/config.inc and change the latter. Go throug each line,
and decide where the database is (ie FQDN - Fully Qualified Domain Name
or IP address - of the LDAP server), what's the base dn of your
QMailLDAP objects etc.

  Domain layout        Organization layout    Organization layout/mixed
  =============        ===================    =========================
  dc=com               c=SE                   c=SE
    dc=fredriksson       ou=Fredriksson         ou=Fredriksson
      ou=People            ou=People              cn=User Name1
        uid=usename          uid=username       ou=Winas
      ou=Groups            ou=Groups              cn=User Name2
        cn=groupname         cn=groupname       
    dc=winas             ou=Winas
      ou=People            ou=People
        uid=usename          uid=username
      ou=Groups            ou=Groups
        cn=groupname         cn=groupname

In the first column is two 'domains' - Fredriksson and Winas. What this
means is that users are under the 'ou=People' object and groups are
under the 'ou=Groups'. Each under the actual 'domain' (dc) object.

The 'domain' refer to the 'basetree' (dc=fredriksson/dc=winas and
ou=Fredriksson/ou=Winas in these two examples), NOT to the domainname!
In the first two columns, I use the top DN (dc=com or c=SE) as base
search in phpQLAdmin.

This layout is configured by defining PQL_LDAP_SUBTREE_USERS and/or
PQL_LDAP_SUBTREE_GROUPS, so without these, you CAN get a flat layout,
but please don't.


The third layout is what I would like to call 'mixed'. It don't
separate users under ou=People etc, but directly under the branch and
users don't have the UID attribute but is using CN as part of their
RDN.

Also, you shouldn't mix the layouts types in one database. What you
should do, is configure multiple top suffixes in your LDAP database
(multiple database backends with different suffixes). phpQLAdmin is
since version 2.0.10 able to cope with that, and show all database as
one.


Problematic database layout
~~~~~~~~~~~~~~~~~~~~~~~~~~~
I can't catch everything. I have to put limitation somewhere. I don't
like telling you how you should structure your database, but there's
no way I'll be able to figure everything out automatically just by
querying the database. One such layout is pictured below.

  o=Domain Branch 1
    ou=People
      cn=Branch1, User1
      cn=Branch1, User2
      [etc]
    o=Domain Branch 2
      cn=Branch2, User1
      cn=Branch2, User2
      [etc]
    o=Domain Branch 3
      ou=People
        cn=Branch3, User1
        cn=Branch3, User2
        [etc]
  o=Domain Branch 4
  [etc]

Now, what's wrong with this layout? Well, for starters the problem isn't
the 'Domain Branch 1' and 'Domain Branch 4'. They reside in completly 
different databases (configured using 'suffix' and 'database' in slapd.conf).
The problem is that domain branch two and three is 'separate' entities
from 'Domain Branch 1'. That is, they shouldn't really be there...

The reason for this is that when looking at the left frame (the user list
frame), everything will at first glance look ok. But looking closer, you'll
see that users from Domain Branch two to three will end up below the
'Domain Branch 1' folder tree, like below (yes, users will end up in two
places). And that's not all. A similar list will be shown when going to
the 'Registered Users' for 'Domain Branch 1'. ALL users will end up there.

  o=Domain Branch 1
    ou=People
      cn=Branch1, User1
      cn=Branch1, User2
      cn=Branch2, User1
      cn=Branch2, User2
      cn=Branch3, User1
      cn=Branch3, User2
      [etc]
    o=Domain Branch 2
      cn=Branch2, User1
      cn=Branch2, User2
      [etc]
    o=Domain Branch 3
      ou=People
        cn=Branch3, User1
        cn=Branch3, User2
        [etc]

Not quite the intended behaviour. The reason for this is that the 'user
retreival function' (pql_user_get()) isn't smart enough. And there's no
way I'll fully be able to fix this... I had some preliminary patches,
but that broke stuff all over the place, so it won't be applied untill
much later...

Now, the solution isn't something I like to impose on you, but I don't
have much choice. Or, rather YOU don't have much choice if you want to
use phpQLAdmin. All branches (one through three) should be flattened
slightly and put under ONE container. You don't have to add/remove
the ou=People container(s), they are perfectly ok, but users can't
like _to_ deep below the branch 'folder'.

  o=Common Container
    o=Domain Branch 1
      ou=People
        cn=User 1
        cn=User 2
        [etc]
    o=Domain Branch 2
      cn=User 1
      cn=User 2
      [etc]
    o=Domain Branch 3
      ou=People
        cn=User 1
        cn=User 2
        [etc]
  o=Domain Branch 4
  [etc]

Domain branch four does not need to be moved or changed (unless starts
looking like the first branch, which I guess is a high probability :).


Configuration in LDAP
~~~~~~~~~~~~~~~~~~~~~
With version 2.0.5, it's possible to have site specific configurations
in the database and with 2.0.10 it's a requirement. It is saved into
the topmost RDN's ('dc=com' and 'c=SE' in my two examples above) objects
and also in each branch (dc=fredriksson, ou=Fredriksson etc above),
so make sure you have access to modify these objects before saving a
site global value.

As said, since 2.0.10 it's a requirement to set the LDAP object
configuration, so as soon as you've logged in for the first time,
find the 'Show configuration' page and set all configuration values.
To be able to fully see all options, you will have to enable 'Advanced
mode' and have write access (and have the 'administrator' attribute) to
the topmost DN (dc=com and c=SE above).


Making sure you have write access to the database is a matter of the
LDAP server, not phpQLAdmin so consult your LDAP servers documentation
on how to do this. The 'ACL' stuff in phpQLAdmin isn't used for
real access control, it's more a fact of specifying what you can SEE.

If you only have the required objectclasses (top and/or domain in a
domain layout for example), phpQLAdmin will add the two objectclasses
'phpQLAdminConfig' and 'phpQLAdminBranch' to the object before it
writes the configuration, so backward compability should be ok with an
non-phpQLAdmin created domain/branch. If it's not, please report a bug
at the mailinglist phpqladmin@bayour.com.


Schema issues
~~~~~~~~~~~~~
There is a couple of problems with the phpQLAdminBranch objectclass.
One is is the 'defaultDomain' attribute. It exists in both the
qmailControl.schema distributed with the QmailLDAP/Controls patch and
in the phpQLAdmin.schema distributed with phpQLAdmin. If you don't use
the QmailLDAP/Controls patch, you will have to uncomment the attribute
from the phpQLAdmin.schema before you restart your LDAP server. The
attribute is defined on lines 299 to 303 in the phpQLAdmin.schema, so
remove the leading dashes (#) on those lines.

Another 'problem' with the schema is the Kerberos stuff. Kerberos
Realm Name (krb5RealmName) and Kerberos Principal Name (krb5PrincipalName)
is defined in krb5-kdc.schema that came with slapd, but have with resent
versions of OpenLDAP been discontinued. If you're not using that schema,
then either uncomment the lines 233 through 243 or remove the attributes
from the MAY clause of the phpQLAdminConfig objectclass (line 348 to 350).
The kerberos stuff in the schema is just a 'hack' until we get REAL
Kerberos/AFS support in PHP.


Kerberos principal creation
~~~~~~~~~~~~~~~~~~~~~~~~~~~
As of version 2.0.10, phpQLAdmin have (very) rudimentary support for
creating the corresponding Kerberos principal in the KDC. This is
solely done in the user creation script (example script 'create_user.pl'
have been included for quite some time and have been updated to show
how it's done). To give this script write access to a remote Kerberos
database, we need to have a special principal and a keytab for this
principal so that we can do 'unattended administration' (ie script
vise).

My setup consists of creating the principal 'phpQLAdmin', exporting
that principal into a keytab (krb5.keytab.phpQLAdmin) and giving the
principal 'phpQLAdmin' full access to the Kerberos database in the
Kerberos KAdmind ACL file. How to do this is documented in your
Kerberos system documentations. 

NOTE: This might be a security hole, because if your webserver is
compromised, so will your Kerberos database. And if the Kerberos
database is compromised, "you're screwed"! So be very carefull before
deciding to do this.


To be able to create a Kerberos principal, you will have to have
'KERBEROS' defined in the Password encryption schemes (see the 'Show
configuration' page). You will then see five more configuration
options in the 'Global configuration' section. Shown below, with
example definitions:

	Kerberos realm			TEST.ORG
	Kerberos admin server		kerberos.test.org
	Kerberos admin principal	phpQLAdmin  
	Kerberos admin keytab		/etc/krb5.keytab.phpQLAdmin  
	Path to Kerberos kadmin command	/usr/sbin  

Without ALL (!) of these values, the (example) script will not even
TRY to create a Kerberos principal (actually, phpQLAdmin won't call
the script).

Modifying or deleting the principal when deleting the user is not
yet implemented.


Templates
~~~~~~~~~
As of version 2.0.10, phpQLAdmin have rudimentary support for user and
domain/branch templates. This configured in the 'Show phpQLAdmin
configuration' page. For a new installation, 'Password encryption
schemes', 'User objectclasses' and 'Domain objectclasses' will be
empty. You will have to setup this for your self. What objectclasses
should your user objects have? What objectclasses should your
domain/branch objects have etc... This require knowledge on how LDAP
works!

Also look at the file README.virtual for some more examples and notes
on schema issues.


Administrator login
~~~~~~~~~~~~~~~~~~~
To be able to login to the LDAP server from phpQLAdmin, the object
you're using for login must have the possibility/authority to do a
simple bind. That usually means that there have to be a 'userPassword'
attribute in the object. Only having the password in the slapd.conf
file (as example below) won't help.

	rootdn	cn=Manager,....
	rootpw	SecretPWHere


Apache configuration
~~~~~~~~~~~~~~~~~~~~
As of phpQLAdmin version 2.0.18, there is no need to do any modifications
to the PHP configuration (php.ini file). Previosly, you had to enable
'register_globals', but this is not needed any more.


QmailLDAP/Controls restart
~~~~~~~~~~~~~~~~~~~~~~~~~~
Unfortunatly, QmailLDAP/Controls needs to be restarted every time
a configuration option have changed (if they are in LDAP as a
QmailLDAP/Controls object). This is done by creating a cron job
that looks something like the following. The example checks locals
and rcpthosts every five minutes. If a change have been made, it
will restart qmail.

# Check for new locals/rcpthosts in the QmailLDAP/Controls object
5,15,25,35,45,55 * * * * root /var/www/phpQLAdmin/restart_qmail.pl

This example require that phpQLAdmin is installed into /var/www/phpQLAdmin/.
If it isn't on your system, change the path to restart_qmail.pl.

This script require a config file that's named /etc/qmail/.restart_qmail.conf,
and will look like this:

LDAP_SERVER="ldap.example.com"
LDAP_SEARCH="/usr/bin/ldapsearch"
LDAP_CTRLDN="ou=QmailLDAP,dc=example,dc=com"
QMAIL_INIT="/etc/init.d/qmail"
HOSTNAME="qmail.example.com"

You must have the QmailLDAP/Controls object named

cn=qmail.example.com,ou=QmailLDAP,dc=example,dc=com

for this to work.


Automatic updating locals/rcpthosts
attributes in QmailLDAP/Controls object
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As of 2.0.14, phpQLAdmin will automaticly add the domain to any
rcpthosts attribute of your QmailLDAP/Controls object(s).

Locals/RCPTHosts - trick 1
	Automatic replication of locals:	on
	Automatic replication of rcpthosts:	on

	The first locals/rcpthosts trick is when the master email
	server should only have 'locals', and the slaves should
	only have 'rcpthosts' attributes. This is because the master
	have all the domains as local domains and the slaves should
	only accept mails for those domains (but forward them to
	the master).

	This will make phpQLAdmin add the new domain (or the
	additionalDomainName in 'locals' on the master, and in the
	'rcpthosts' on the slave(s).

	For this to work perfectly, you must already have (manually)
	added a domain to locals and rcpthosts on the respective
	host object, because phpQLAdmin will add the domain to the
	object(s) which HAVE locals, and rcpthosts to object(s) which
	have rcpthosts.

	So for the very first branch/domain you add, disable automatic
	replication (this is the default), then add domain manually
	to your QmailLDAP/Controls objects locals or rcpthosts attribute.
	THEN you can enable automatic replication.

	If you do NOT do this (ie, start out with automatic replication
	of both locals and rcpthosts), you will end up with the domain
	added to ALL your QmailLDAP/Controls locals attribute, which
	will say to qmail that the domain is local on ALL hosts, which
	will most likley fail (eventually any way).

Locals/RCPTHosts - trick 2
	Automatic replication of locals:	off
	Automatic replication of rcpthosts:	on

	Another example would be if you have one or more main servers
	and a bunch of slave servers. The slave servers don't have
	any local(s) domains, only rcpthosts. That is, it does not
	have any local accounts, it just listens (and receive mails
	for) a(ll) domain(s). But the master email servers does not
	have ALL domains local, only specific ones. 

	Let's say you have two main mailservers and x slaves (the slaves
	is not of interest here, they have ALL domains in rcpthosts).

		Master server	Slave server
		~~~~~~~~~~~~~	~~~~~~~~~~~~
		bayour.com	frans.org
		test.org	turbo.se

	To be able to control to which server a new domain go (let's say
	we're adding 'fredriksson.dj' to the system), you will have to
	disable automatic replication of locals (but leave it on for
	rcpthosts). Then, when you're adding defaultDomain (or additional
	domain name), you will get the question on which host (ie,
	QmailLDAP/Controls object) to add the domain to. Since rcpthosts
	is automaticly replicated, but locals is not, the domain will be
	added to ALL (!) hosts rcpthosts attribute, EXEPT the one which
	you choosed for 'locals' addition. This means that the OTHER master
	server will have the domain in rcpthosts (ie, it will be a slave
	for this domain).

	If this isn't desired, disable automatic replication completely!

Having automatic replication of locals=on and rcpthosts=off (the
opposit of trick 2) is of little use, since replication of locals will
add the domain to all hosts (QmailLDAP/Controls object) and rcpthosts
will not be written if the domain exists in locals...


If neither 'trick 1' nor 'trick 2' is what you want, tell me (as verbose
as you can, with examples) and I'll see what I can do. Until then, you
will have to disable automatic replication on both locals and rcpthosts,
and either specify what to write where (when adding domain to default
or additional domain for branch).


National characters (UTF-8 encoding)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As of v2.0.14, it is possible to create objects with full international
support (ie, use national characters wherever even in the DN's). One
exeption to this is if branches is ordered by the 'dc' attribute (domain
objectclass). The 'dc' attribute does not allow UTF-8 encoded strings...

National characters is now also possible in the FQDN (Fully Qualified
Domain Name) of the locals/rcpthosts attributes in the QmailLDAP/Controls
object. To enable this, you will have to update the QmailLDAP/Controls
schema. See more in the README.upgrade file (see the 'Upgrading from 2.0.13'
section). Wether QmailLDAP/Controls in itself will allow UTF-8 encoded
email addresses is not known to me at this time. You will have to test
it yourself. If it works, please let me know...


LDAP Server monitoring and status retreival
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As of 2.0.19, phpQLAdmin can retreive more information about the LDAP server.
Those values are stored below 'cn=Monitor', and are only availible in
OpenLDAP 2.1 and newer. As of 2.1.22, there's not that much information about
the databases (suffixes), but hopfully that have improved in 2.2.
This information will only be availible if: a) you're running in Advanced
mode, b) you're a site administrator (you're listed in the base dn's) and
c) the monitor backend is enabled and readable by the user logging in.
If all three cases are true, then there will be three extra links below
the Home->LDAP Server Configuration tree.


For more information on installations, please view doc/index.php through
your web browser. Note though that documentation is not my stronges side
while coding, so it is much out of date. I will evenually get to it,
but... :)
