README for authd SQL <-> LDAP gateway ( v1.2 ) ===================================== Authd is a communication daemon written for Cable & Wireless Europe. The goal was to provide a fast LDAP interface to C&W databases. To do such, I used the iODBC SQL API, so authd can operate any kind of database supported by iODBC, for example Oracle, Sybase, MySQL, Postgres... This distributed version is lighter than the version we currently use, so it can be more usable for everyone. How does it works ----------------- With this tarball comes a patch for OpenLDAP 2.0.x, which modifies the back-passwd backend. Originally, the back-passwd backend uses /etc/passwd as the LDAP source data, my ( quick ) patch make it query a host special port, this is set in the slapd.conf, following this format : authurl host:port When authd receive an LDAP query, it will associate an SQL query, specified on the conf file, SQL results are then mapped to LDAP equivalents, this is what OpenLDAP gets and sends back to the client. [ LDAP client ] | ^ ou=pop3,dc=domain,dc=com ------ | | uid=jdoe | | --- uid=jdoe,userPasswd=eodj... v | [ OpenLDAP ] | ^ ou=pop3,dc=domain,dc=com ------ | | uid=jdoe | | --- login=uid,passwd=userPasswd... v | [ authd ] | ^ SELECT * FROM authtable ------- | | WHERE login=jdoe | | --- login=jdoe,passwd=eodj... v | [ SQL database ] Connections to the SQL databases are persistant so there's no need to open/close the ODBC link, those persistant links grows as the requests number grows, with a limit of "threads", which is set in the conf file ( see below ). Does it works ------------- Yes. Authd is up and running for months now at Cable & Wireless Europe, with very positive results. The databases have some millions entries, all mapped over LDAP for various services such as pop3, imap, ftp... The conf file - READ THIS ------------- ========= ========= . threads: the max thread number you want the daemon to launch. Each thread is a persistant connection to the database. For you to know, for a million entries, we use about 40 threads max. by server. . dsn: the odbc.ini dsn you wan't to use. I will not explain the DSN / odbc.ini stuff here, please reffer to iODBC documentation. . timeout: the fallout time for an odbc connection . tries: ODBC connection attempts before exit'ing . acl: is the pool list allowed to connect to the console mode . admin: the password for console mode . query_init: a health check SQL query, used to detect ODBC connection availability. Set it as small as possible so it don't slow down real queries * SQL to LDAP mappings: for example to map a "login" SQL attribute to the standard userLogin LDAP attribute you'll write : userPassword login * then comes the objectclass list, this _is_ mandatory The mapping part is very important, this is where you associate SQL datas to LDAP attributes. See conf file for example. The query part is the heart of the system, this is where you write the SQL query you want to pass to your "real" database. It has the following format : query_ There can be 2 behaviours here : 1. you wrote a module called , then authd will use this module to answer the query 2. you didn't wrote a module called , then authd will use the generic module to answer the query. You can use as much query_ as you like. IMPORTANT POINT: reffers to ou= in the LDAP query. In other words, when you'll query OpenLDAP with, let's say : ldapsearch -h host -b "ou=smtp,dc=company,dc=com" domain=isp.com authd will look to this query line : query_smtp PLEASE CAREFULLY READ the configuration file for further examples. Writing modules --------------- If your database is not too complex the generic module should do the job well, anyway modules are, imho, simple to write. Let's say we want to write a service called "false" : int getfalse(DB *dbi, int fd, char *ou, char *filter) { char query[MAXVAL]="",*filtval,*val; int errcode=0; /* new query */ /* * query field is built with the defined word QUERY and * the char *ou which is always passed as an argument. * Here, we'll have "query_false" */ snprintf(query,MAXVAL,"%s%s",QUERY,ou); /* point associated SQL query */ val=attr2val(query); if (!val) return -1; /* get filter value ( uid=xxx ) */ filtval=getval(filter,'='); if (!filtval) { free(val); return -1; } /* get query result */ /* here is the real SQL query */ /* arguments dbi : the database connection id fd : client socket NULL : for future use val : the query, caught from conf file filtval : filter value ... : you can add as much filter values as you want, as long as your query (in the conf file) contains the same number of '%s' */ errcode=simplequery(dbi,fd,NULL,val,filtval); free(val); return errcode; } You'll find this code on the modules/ directory, with associated Makefiles. Misc ---- . DO NOT FORGET to set up the ODBCINI variable ( usually /etc/odbc.ini ) . test the ODBC connectivity with the console mode : telnet admin > help > sql sql> some sql query sql> quit > quit . For analysis purposes, authd can answer a HTTP query on its port, it will show you current connexions. --- iMil