Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

ldap_object.cc

Go to the documentation of this file.
00001 /*************************************************************************/
00002 /*  LDAPCONF - Linuxconf module for LDAP operation.
00003     
00004     Copyright (C) 1999,2000,2001 Stein Vråle <stein@terminator.net>
00005 
00006     This program is distributed in the hope that it will be useful,
00007     but WITHOUT ANY WARRANTY; without even the implied warranty of
00008     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
00009     GNU General Public License for more details.
00010     
00011 **************************************************************************/
00012 /*!  LDAP_OBJECT.cc
00013   
00014     #Specification: Manage ldap data entries and directory access.
00015     This class will store all information for one LDAP object, when it is 
00016     retrived from the directory.
00017     The class provides methods to retrive data from directory, manipulate
00018     it, export and import to other formats, and write it back to the 
00019     directory again.
00020     
00021     TODO: The class should probably be splittet into two or maybe three
00022     classes, as the current object has grown so big, and contain methods
00023     which are totally unrelated to each other. Should not be to hard to
00024     split it, but we need a good design for a new class structure first.
00025 
00026 **************************************************************************/
00027 #pragma implementation
00028 #include <unistd.h>
00029 #include <string.h>
00030 #include <stdlib.h>
00031 #include <subsys.h>
00032 #include <confdb.h>
00033 #include <ctype.h>
00034 #include "ldapconf_defs.h"
00035 
00036 /*~PROTOBEG~ LDAPOBJECT */
00037 
00038 /*!
00039 
00040   Create and initialize a new object.
00041 
00042 */
00043 PUBLIC LDAPOBJECT::LDAPOBJECT ()
00044 {
00045     D(debugf(4,">>>LDAPOBJECT::CREATE:"));
00046     
00047     init();
00048 }
00049 
00050 /*!
00051 
00052   Create and initialize a new object.
00053   Load named directory profile.
00054 
00055 */
00056 PUBLIC LDAPOBJECT::LDAPOBJECT (const char *profile_name)
00057 {
00058     D(debugf(4,">>>LDAPOBJECT::CREATE(%s)",profile_name));
00059 
00060     init();
00061     load_profile(profile_name);
00062 }
00063 
00064 /*
00065 
00066   Init new object.
00067 
00068 */
00069 PUBLIC void LDAPOBJECT::init ()
00070 {
00071     D(debugf(4,"---LDAPOBJECT::init"));
00072 
00073     // We assemble a unique name for the temporary ldif file
00074     static int instance=0;
00075     char buf[PATH_MAX];
00076     snprintf (buf,PATH_MAX-1,"/var/run/ldapconf.entry.%d.%d",getpid(),instance++);
00077     ldapconf_entry = strdup(buf);
00078     this->form = NULL;
00079     reset();
00080 }
00081 
00082 /*!
00083 
00084   Destroy object and free allocations.
00085 
00086 */
00087 PUBLIC LDAPOBJECT::~LDAPOBJECT ()
00088 {
00089     free (ldapconf_entry);
00090     if (this->form != NULL) delete this->form;
00091 
00092     D(debugf(4,"<<<LDAPOBJECT::DESTROY:"));
00093 }
00094 
00095 /*****************************
00096 
00097   LDAPOBJECT directory methods
00098 
00099 *****************************/
00100 
00101 /*!
00102 
00103     LDAPOBJECT.reset 
00104     Empty the local object
00105 
00106 */
00107 PUBLIC int LDAPOBJECT::reset ()
00108 {
00109     D(debugf(4,"---LDAPOBJECT::reset:"));
00110     reset_data();
00111 
00112     filter = "";
00113     attr = "";
00114     base = "";
00115     binddn = "";
00116     bindpw = "";
00117     host = "";
00118     port = "";
00119 
00120     ldif_format = 0;
00121 
00122     return 0;
00123 }
00124 
00125 /*!
00126 
00127     LDAPOBJECT.reset_data 
00128     Empty all attributes and objectclasses
00129 
00130 */
00131 PUBLIC int LDAPOBJECT::reset_data ()
00132 {
00133     D(debugf(4,"---LDAPOBJECT::reset_data:"));
00134 
00135     atlist.remove_all();
00136     oclist.remove_all();
00137 //  command_line.setfrom("");
00138 
00139     return 0;
00140 }
00141 
00142 /*!
00143     LDABOBJECT.command
00144     
00145     Build commandline from standard, common, and custom settings.
00146     Run the command, and return the results.
00147 */
00148 PUBLIC int LDAPOBJECT::command(const char *command, SSTRINGS&resmsg)
00149 {
00150     D(debugf(4,"-->LDAPOBJECT::ldap_command: %s",command));
00151     SSTRING parameters;
00152     const char *args;
00153     int ret;    
00154     
00155     /* Directory config */
00156     if (!binddn.is_empty())
00157         parameters.appendf(" -D %s",binddn.get());
00158     if (!bindpw.is_empty()) 
00159         parameters.appendf(" -w %s",bindpw.get());
00160     if (!host.is_empty()) 
00161         parameters.appendf(" -h %s",host.get());
00162     if (!port.is_empty()) 
00163         parameters.appendf(" -p %s",port.get());
00164     
00165     /* Standard args */
00166     parameters.appendf(" %s",mode_openldap_params.get());
00167 
00168     if (!strcmp(command,"ldapsearch")) {
00169         parameters.append(" -LLL"); // Removes comment and version indication (OpenLdap 2.x)
00170         if (!base.is_empty())
00171             parameters.appendf(" -b %s",base.get());
00172     }
00173 
00174     /* OpenLDAP version depended parameters */
00175     if (!mode_openldap_version.cmp("2")) { 
00176         // This is for 2.x
00177         if (command != "ldappasswd"){
00178             // Add LDAP protocol version for this directory
00179             if (this->c_profile->getval("profile","protocol")){
00180                 // User defined
00181                 parameters.appendf(" -P %s",this->c_profile->getval("profile","protocol",mode_ldap_protocol.get()));
00182             }
00183             else{
00184                 // Use default
00185                 parameters.appendf(" -P %s",mode_ldap_protocol.get());
00186             }
00187         }
00188         // Add option to disable SASL with OL-2.x
00189         parameters.append(" -x");
00190     }
00191     
00192     /* Custom args */
00193     if (!command_line.is_empty())
00194         parameters.appendf(" %s",command_line.get());
00195     
00196     /* Filter */
00197     if (!filter.is_empty() && command == "ldapsearch")
00198         parameters.appendf(" %s",filter.get());
00199 
00200     /* Attr */
00201     if (!attr.is_empty() && command == "ldapsearch" )
00202         parameters.appendf(" %s",attr.get());
00203 
00204     args = parameters.get();
00205         
00206 
00207     /* Run command*/
00208     ret = sys_command (command,args,resmsg);
00209 
00210     D(debugf(4,"<--LDAPOBJECT::ldap_command:"));
00211     return ret;
00212 }
00213 
00214 /*!
00215     LDAPOBJECT.add 
00216 
00217     Add object to directory.
00218 */
00219 PUBLIC int LDAPOBJECT::add ()
00220 {
00221     D(debugf(4,"-->LDAPOBJECT::ADD"));
00222     int ret=0;
00223     SSTRINGS resmsg;
00224 
00225     export_ldif(ldapconf_entry);
00226 
00227     command_line.setfrom(" -a"); // Add
00228     command_line.appendf(" -f %s",ldapconf_entry); // Entry
00229 
00230     /* Run command*/
00231     ret = command ("ldapmodify",resmsg);
00232     
00233     /* Remove tmp entry file */
00234     unlink(ldapconf_entry);
00235 
00236     D(debugf(4,"<--LDAPOBJECT::ADD"));
00237     return ret;
00238 }
00239 
00240 /*!
00241 
00242     LDAPOBJECT.modify
00243     Update object to database
00244 
00245 */
00246 PUBLIC int LDAPOBJECT::modify ()
00247 {
00248     D(debugf(4,"-->LDAPOBJECT::MODIFY"));
00249     int ret=0;
00250     SSTRINGS resmsg;
00251 
00252     export_ldif(ldapconf_entry);
00253 
00254     command_line.setfrom(" -r");
00255     command_line.appendf(" -f %s",ldapconf_entry);
00256 
00257     /* Run command*/
00258     ret = command ("ldapmodify",resmsg); 
00259     
00260     /* Remove tmp entry file */
00261     unlink(ldapconf_entry);
00262 
00263     D(debugf(4,"<--LDAPOBJECT::MODIFY"));
00264     return ret;
00265 }
00266 
00267 /*!
00268 
00269   LDAPOBJECT.export_ldif
00270   Write object data to file in ldif format
00271 
00272 */
00273 PUBLIC int LDAPOBJECT::export_ldif(const char *path)
00274 {
00275     int ret=0;
00276 
00277     /* Remove creator/modifier stamps */
00278     at_del("modifytimestamp");
00279     at_del("modifiersname");
00280     at_del("createtimestamp");
00281     at_del("creatorsname");
00282 
00283     // Remove duplicates
00284     // \bug : Doing this will bypass the problem with duplicates of some entries (eg mail2),
00285     // but it will also hide the cause of the real problem - why/where do the duplicates come from?
00286     // it does not work , I think the problem is the file modify just add things but never tell openldap to remove attributes so they become duplicates !
00287     atlist.remove_dups();
00288     oclist.remove_dups();
00289 
00290     /* Build dataentry */
00291     FILE *fout = fopen (path,"w");
00292     if (fout != NULL){
00293         fprintf (fout,"%s\n",dn.get());
00294         D(debugf(4,"LDIF: %s",dn.get()));
00295 //write objectclass before attributes
00296 
00297         for (int i=0; i<oclist.getnb(); i++){
00298             fprintf (fout,"%s\n",oclist.getitem(i)->get());
00299             D(debugf(4,"LDIF: %s",oclist.getitem(i)->get()));
00300         }
00301 
00302         for (int i=0; i<atlist.getnb(); i++){
00303             fprintf (fout,"%s\n",atlist.getitem(i)->get());
00304             D(debugf(4,"LDIF: %s",atlist.getitem(i)->get()));
00305         }
00306 
00307         fclose (fout);
00308     }
00309 
00310     return ret;
00311 }
00312 
00313 /*!
00314 
00315     LDAPOBJECT.del
00316     Delete object from database
00317 
00318 */
00319 PUBLIC int LDAPOBJECT::del ()
00320 {
00321     D(debugf(4,"---LDAPOBJECT::DEL"));
00322     int ret=0;  
00323 
00324     SSTRINGS resmsg;
00325 
00326     command_line.setfrom(dn.get());
00327 
00328     /* Run command*/
00329     ret = command ("ldapdelete",resmsg);
00330 
00331     return ret;
00332 }
00333 
00334 /*!
00335 
00336     LDAPOBJECT.search
00337     Search uniq object
00338 
00339 */
00340 PUBLIC int LDAPOBJECT::search ()
00341 {
00342     D(debugf(4,"-->LDAPOBJECT::SEARCH"));
00343     SSTRINGS data;
00344     char name[ATTR_NAME_MAX];
00345     char val[ATTR_VAL_MAX];
00346 
00347     D(debugf(4,"search filter: %s\n",filter.get()));
00348     reset_data();
00349 
00350     /* Run ldapsearch command*/
00351     command("ldapsearch",data);
00352 
00353     /* Split the objects */
00354 
00355     int c = 1;  /* Line counter */ 
00356     int d;      /* Number of lines */
00357     int idx = 0;    /* Object index number */   
00358     int i = 1; /* Object internal count */
00359     
00360     d = data.getnb();
00361     c = 0;
00362     c++; /* Skip command message */
00363 
00364     while (c < d ) {
00365         SSTRING *s = data.getitem(c);
00366         s->strip_end();
00367 
00368         const char *a = str_skip(s->get());
00369 
00370         if (s->is_empty()) { // Empty line is object seperator
00371             i=0;
00372         } else if (s->strstr("dn:") != 0) { // DN line found
00373             dn.setfrom(s->get());
00374             idx++;
00375             i=1;
00376             D(debugf(6,"search line=%d found %s\n",dn.get()));
00377         } else if (ldif_splitline(a,name,val)==0) {
00378             if (strncasecmp(name,"objectClass",11) == 0) {
00379                 oc_add(val);
00380             }
00381             else{
00382                 at_add(name,val);
00383             }
00384         } else { // Should not happen
00385             D(debugf(4,"search Warning - undecoded ldif line %s\n",s->get()));
00386         }
00387         c++;
00388     }
00389     return idx;
00390 }
00391 
00392 /*!
00393 
00394     LDAPOBJECT.search_list
00395     Search and return resultlist
00396 
00397 */
00398 PUBLIC int LDAPOBJECT::search_list (SSTRINGS &lst)
00399 {
00400     D(debugf(4,"-->LDAPOBJECT::SEARCH_LIST"));
00401     int ret=0;
00402     SSTRINGS data;  
00403 
00404     reset_data();
00405 
00406     attr.setfrom("dn");
00407 
00408     ret = command ("ldapsearch",data);
00409 
00410     int c = 0;  /* Line counter */ 
00411     int d = 0;      /* Number of lines */
00412     int idx = 0;    /* Object index number */   
00413     int i = 0; /* Object internal count */
00414 
00415     d = data.getnb();
00416     
00417     c++; // Skip the first line, its the ldapsearch commandline
00418 
00419     while (c < d ) {
00420         SSTRING *s = data.getitem(c);
00421         s->strip_end();
00422 
00423         const char *a = str_skip(s->get());
00424 
00425         if (s->is_empty()) { // Empty line is object seperator
00426             i=0;
00427         } else if (s->strstr("dn:") != NULL) { // DN line found
00428             lst.add(new SSTRING(a));
00429             idx++;
00430             i=1;
00431         } // Skip the rest of this object
00432         c++;
00433     }
00434     return idx;
00435 }
00436 
00437 /*!
00438 
00439     LDAPOBJECT.search_list_val
00440     Search and return resultlist, where entries are the values of the key attribute only.
00441 
00442 */
00443 PUBLIC int LDAPOBJECT::search_list_val (SSTRINGS &lst,const char *key)
00444 {
00445     D(debugf(4,"-->LDAPOBJECT::SEARCH_LIST_VAL (%s)",key));
00446     int ret=0;
00447     SSTRINGS data;
00448     char name[ATTR_NAME_MAX];
00449     char val[ATTR_VAL_MAX];
00450 
00451     reset_data();
00452 
00453     attr.setfrom(key);
00454 
00455     ret = command ("ldapsearch",data);
00456 
00457     int c = 0;  /* Line counter */ 
00458     int d = 0;      /* Number of lines */
00459     int idx = 0;    /* Object index number */   
00460     int i = 0; /* Object internal count */
00461 
00462     d = data.getnb();
00463 
00464     c++; // Skip the first line, its the ldapsearch commandline
00465 
00466     while (c < d ) {
00467         SSTRING *s = data.getitem(c);
00468         s->strip_end();
00469 
00470         const char *a = str_skip(s->get());
00471 
00472         if (s->is_empty()) { // Empty line is object seperator
00473             i=0;
00474         } else if (s->strstr("dn:") != NULL) { // DN line found
00475             idx++;
00476             i=1;
00477         } else if (i==1 && ldif_splitline(a,name,val)==0) {
00478             lst.add(new SSTRING(val));
00479             i++;
00480         }
00481         c++;
00482     }
00483     return idx;
00484 }
00485 
00486 /*!
00487 
00488     LDAPOBJECT.search_list_vals
00489     Search and return resultlist, where entries are the values of the specified attributes.
00490     The key attribute must always be specified.
00491 
00492 */
00493 PUBLIC int LDAPOBJECT::search_list_vals (SSTRINGS &lst,const char *key,const char *at_name[])
00494 {
00495     D(debugf(4,"-->LDAPOBJECT::SEARCH_LIST_VALS (%s)(%s)",key,at_name));
00496     int ret=0;
00497     SSTRINGS data;  
00498     char name[ATTR_NAME_MAX];
00499     char val[ATTR_VAL_MAX];
00500 
00501     reset_data();
00502 
00503     attr.setfrom(key);
00504 
00505     int atc = 0;
00506     while (at_name[atc] != NULL){
00507         attr.appendf(" %s",at_name[atc]);
00508         atc++;
00509     } 
00510     
00511     ret = command ("ldapsearch",data);
00512 
00513     int c = 0;  /* Line counter */ 
00514     int d = 0;      /* Number of lines */
00515     int idx = 0;    /* Object index number */   
00516     int i = 0; /* Object internal count */
00517 
00518     d = data.getnb();
00519 
00520     c++; // Skip the first line, its the ldapsearch commandline
00521 
00522     while (c < d ) {
00523         SSTRING *s = data.getitem(c);
00524         s->strip_end();
00525 
00526         const char *a = str_skip(s->get());
00527 
00528         if (s->is_empty()) { // Empty line is object seperator
00529             i=0;
00530         } else if (s->strstr("dn:") != NULL) { // DN line found
00531             idx++;
00532             i=1;
00533         } else if (i==1 && ldif_splitline(a,name,val)==0) {
00534             lst.add(new SSTRING(a));
00535             i++;
00536         } else if (ldif_splitline(a,name,val)==0) {
00537             lst.getitem(idx-1)->appendf("\t%s",a);
00538             i++;
00539         }
00540 
00541         c++;
00542     }
00543     return idx;
00544 }
00545 
00546 /**********************************************************************
00547 
00548   LDAPOBJECT datamanipulation
00549 
00550   The object data will be stored internally using SSTRING objects.
00551   Each SSTRING object will hold one attribute name and value, using 
00552   the same format as the one used in LDIF data:
00553   
00554   attrname: attrvalue
00555 
00556   The SSTRINGS object will be used to hold lists of related LDAP data.
00557 
00558   Following is a set of small methods to handle the internal datastorage.
00559   
00560   External functions should if possible try to use these methods when 
00561   dealing with the data, so it will be easy to change the internal data
00562   storage system later.
00563 
00564   This interface is not yet completed, but most of the current functions
00565   in ldapconf make use of it already.
00566 
00567 ***********************************************************************/
00568 
00569 /*!
00570     LDAPOBJECT.dn_set
00571 
00572     Set dn.
00573 */
00574 PUBLIC int LDAPOBJECT::dn_set (const char *val)
00575 {   
00576     int ret=0;
00577 
00578     dn.setfromf("dn: %s",val);
00579     
00580     D(debugf(4,"---LDAPOBJECT::dn_set (%s)",val));
00581     return ret;
00582 }
00583 
00584 /************** 
00585 
00586     Attributes 
00587 
00588 **************/
00589 
00590 /*!
00591     LDAPOBJECT.at_list
00592     Copy all attribute names to the list.
00593     Return number of attributes.
00594 */
00595 PUBLIC int LDAPOBJECT::at_list (SSTRINGS &lst)
00596 {
00597     int n = atlist.getnb();
00598     D(debugf(4,"at_list number of attr=%d\n",n));
00599 
00600     for (int i=0; i<n; i++){
00601         SSTRINGS tb;
00602         if (SSTRING *it = atlist.getitem(i)){
00603             str_splitline(it->get(),':',tb);
00604             if (tb.getitem(0)) {
00605                 lst.add (new SSTRING( tb.getitem(0)->get()) );
00606                 D(debugf(6,"LDAPOBJECT::at_list found attr %s\n",tb.getitem(0)->get()));
00607             }
00608         }
00609     }
00610     return n;
00611 }
00612 
00613 /*!
00614     LDAPOBJECT.at_get
00615     
00616     Locate the value of the named attribute.
00617     Return NULL if the name is not defined.
00618     Eventual quote surrounding the value are removed.
00619 */
00620 PUBLIC const char* LDAPOBJECT::at_get (const char *name)
00621 {
00622     return LDAPOBJECT::at_get(name,1);
00623 }
00624 
00625 /*!
00626     LDAPOBJECT.at_get
00627     
00628     Locate the value of the k named attribute.
00629     Return NULL if the name is not defined.
00630     Eventual quote surrounding the value are removed.
00631 */
00632 PUBLIC const char* LDAPOBJECT::at_get (const char *name, int k)
00633 {
00634     char tmp[1000];
00635     const char *ret = NULL;
00636     SSTRING *it = locateassign(name,k);
00637 
00638     if (it != NULL){
00639         const char *pt = it->strchr(':');
00640         if (pt != NULL){
00641             ret = pt+2;
00642             if (ret[0] == '"'){
00643                 ret++;
00644                 strncpy (tmp,ret,sizeof(tmp));
00645                 strip_end (tmp);
00646                 int len = strlen(tmp)-1;
00647                 if (len >= 0 && tmp[len] == '"') tmp[len] = '\0';
00648                 ret = tmp;
00649             }
00650         }
00651     }
00652 
00653     D(debugf(6,"LDAPOBJECT::at_get %s: %s\n",name,ret));
00654     return ret;
00655 }
00656 
00657 /*!
00658     LDAPOBJECT.at_getall
00659 
00660     Copy multiple attribute values from the named attribute to the list.
00661     Return number of values found.
00662 */
00663 PUBLIC int LDAPOBJECT::at_getall (const char *name,SSTRINGS &lst)
00664 {
00665     int num = 0;
00666 
00667     num = locate(name,lst);
00668 
00669     D(debugf(6,"LDAPOBJECT::at_getall name=%s num=$d \n",name,num));
00670     return num;
00671 }
00672 
00673 /*!
00674     LDAPOBJECT.at_getname
00675 
00676     Return the name of attribute n.
00677     Return NULL if not found.
00678 */
00679 PUBLIC const char* LDAPOBJECT::at_getname (int num)
00680 {
00681     char name[ATTR_NAME_MAX];
00682     const char *ret = NULL;
00683 
00684     SSTRING *it = atlist.getitem(num);
00685 
00686     if (it != NULL){        
00687         SSTRINGS tb;
00688         str_splitline(it->get(),':',tb); // 2.0
00689         strncpy(name,tb.getitem(0)->get(),ATTR_NAME_MAX);
00690         strip_end(name);
00691         ret = name;
00692     }
00693 
00694     D(debugf(6,"LDAPOBJECT::at_getname %d=%s\n",num,name));
00695     return ret;
00696 }
00697 
00698 /*!
00699     LDAPOBJECT.at_getval
00700 
00701     Return the value of attribute n.
00702     Return NULL if not found.
00703 */
00704 PUBLIC const char* LDAPOBJECT::at_getval (int num)
00705 {
00706     char val[ATTR_VAL_MAX];
00707     const char *ret = NULL;
00708 
00709     SSTRING *it = atlist.getitem(num);
00710 
00711     if (it != NULL){        
00712         SSTRINGS tb;
00713         str_splitline(it->get(),':',tb); // 2.0
00714         strncpy(val,tb.getitem(1)->get(),ATTR_VAL_MAX);
00715         strip_end(val);
00716         ret = val;
00717     }
00718 
00719     D(debugf(6,"LDAPOBJECT::at_getval %d=%s\n",num,val));
00720     return ret;
00721 }
00722 
00723 /*!
00724     LDAPOBJECT.at_set
00725 
00726     Update or add an attribute STR value.
00727     It will replace any existing value.
00728 */
00729 PUBLIC int LDAPOBJECT::at_set (const char *name ,const char *val)
00730 {
00731     D(debugf(4,"-->LDAPOBJECT::at_set:str (%s,%s)",name,val));
00732     int ret=0;
00733     
00734     // Don't save empty attributes.
00735     // \bug  - sometimes it should be saved as empty in directroy, sometimes not - 
00736     // we need something to handle both situations  
00737     if (strlen(val) == 0) {
00738         D(debugf(4,"<--LDAPOBJECT::at_set:str NULL value - not saved"));
00739         return 0;
00740     }
00741 
00742     // we must remove extra numbers at the end 
00743     // to manage multi attribute values 
00744     // ie we want to add mail not mail3 or mail5
00745     // The number must be removed before we can search 
00746     // for other dublicates
00747 
00748     char * basename=strdup(name);
00749     char * p=basename+strlen(basename)-1;   
00750     bool multivalue = false;
00751     D(debugf(4,"p=(%c)",*p));
00752     
00753     while (isdigit(*p)) {
00754         D(debugf(4,"at_set multiattribute value %c",*p));
00755         *p = '\0';
00756         p--;
00757         multivalue=true;
00758     }
00759     
00760     // Use at_add instead of at_set if this is multivalue and current index >= 2
00761     if (multivalue) {
00762         at_add(basename,val);
00763         return ret;
00764     }
00765 
00766     D(debugf(4,"str=(%s) p=(%c)",basename,*p));
00767     // Check for non-ascii char, if attr is not a password field. 
00768     // \bug : total rewrite when we find out how to handle this problem
00769     if (strncasecmp(name,"userpassword",ATTR_VAL_MAX)){ 
00770         str_conv_ascii(val);
00771     }
00772 
00773     // Got our real name, now search for duplicates 
00774     SSTRING *it = locateassign(basename);
00775     if (it == NULL){
00776         it = new SSTRING("");
00777         atlist.add (it);
00778     }
00779 
00780     it->setfrom (basename);
00781 
00782     // lowering attribute name only, not the value
00783     // we have to lower because comparing the values with strncasecmp 
00784     // is not enough as the attribute will be indexed by using its name 
00785     // so we would miss it sometimes
00786     it->to_lower();
00787 
00788     // \bug : temporary support for base64 passwords, just to see if it helps.
00789     if (!it->cmp("userpassword"))
00790         it->append(":");
00791 
00792     it->appendf(": %s",val);
00793     it->strip_end(); // Make sure it is clean
00794 
00795     D(debugf(4,"<--LDAPOBJECT::at_set:str (%s)",it->get()));
00796     return ret; 
00797 }
00798 
00799 /*!
00800     LDAPOBJECT.at_set
00801 
00802     Update or add an attribute NUM value.
00803     Will replace existing value.
00804 */
00805 PUBLIC int LDAPOBJECT::at_set (const char *name ,int val)
00806 {
00807     D(debugf(4,"-->LDAPOBJECT::at_set:num (%s,%i)",name,val));
00808     int ret=0;
00809 
00810     SSTRING *it = locateassign(name);
00811     if (it == NULL){
00812         it = new SSTRING("");
00813         atlist.add (it);
00814     }
00815     it->setfrom (name);
00816     // lowering attribute name only, not the value
00817     it->to_lower();
00818 
00819     it->appendf(": %d",val);    
00820 
00821     D(debugf(4,"<--LDAPOBJECT::at_set:num (%s)",it->get()));
00822     return ret;
00823 }
00824 
00825 /*!
00826     LDAPOBJECT.at_add
00827 
00828     Add attribute STR value.
00829     Should always add a new attr value, even if an attr with same name already exist,
00830     to support multivalue fields.
00831     (Use at_set to replace attributes.)
00832 */
00833 PUBLIC int LDAPOBJECT::at_add (const char *name ,const char *val)
00834 {
00835     D(debugf(4,"-->LDAPOBJECT::at_add:str (%s,%s)",name,val));
00836     int ret=0;
00837 
00838     if (strlen(val) == 0) {
00839         D(debugf(4,"<--LDAPOBJECT::at_add:str NULL value - not saved"));
00840         return ret;
00841     }
00842     
00843     // Check for non-ascii char, if attr is not a password field. 
00844     // \bug : total rewrite when we find out how to handle this problem
00845     if (strncasecmp(name,"userpassword",ATTR_VAL_MAX)){ 
00846         str_conv_ascii(val);
00847     }
00848     
00849     SSTRING *it = NULL;
00850     if (it == NULL){
00851         it = new SSTRING("");
00852         atlist.add (it);
00853     }
00854     it->setfrom (name);
00855     // lowering attribute name only, not the value
00856     it->to_lower();
00857 
00858     //! \bug : temporary support for base64 passwords, just to see if it helps.
00859     if (!it->cmp("userpassword"))
00860         it->append(":");
00861     
00862     it->appendf(": %s",val);
00863 
00864     D(debugf(4,"<--LDAPOBJECT::at_add:str (%s)",it->get()));
00865     return ret;
00866 }
00867 
00868 /*!
00869     LDAPOBJECT.at_add
00870 
00871     Add attribute NUM value.
00872     Will not replace existing values.
00873 */
00874 PUBLIC int LDAPOBJECT::at_add (const char *name ,int val)
00875 {
00876     D(debugf(4,"-->LDAPOBJECT::at_add:num (%s,%i)",name,val));
00877     int ret=0;
00878 
00879     SSTRING *it = locateassign(name);
00880     if (it == NULL){
00881         it = new SSTRING("");
00882         atlist.add (it);
00883     }
00884 
00885     it->setfrom (name);
00886 
00887     // lowering attribute name only, not the value
00888     it->to_lower();
00889     it->appendf(": %d",val);
00890 
00891     D(debugf(4,"<--LDAPOBJECT::at_set:num (%s)",it->get()));
00892     return ret;
00893 }
00894 
00895 /*!
00896     LDAPOBJECT.at_del
00897 
00898     Delete all instances of the named attribute.
00899 */
00900 PUBLIC int LDAPOBJECT::at_del (const char *name)
00901 {
00902     D(debugf(4,"-->LDAPOBJECT::at_del  (%s)",name));
00903     int ret=0;
00904 
00905     while (1){
00906         SSTRING *it = locateassign (name);
00907         if (it == NULL) break;
00908         ret = atlist.remove_del(it);
00909         D(debugf(3,":at_del: Deleting (%s)",name));
00910     }
00911     
00912     D(debugf(4,"<--LDAPOBJECT::at_del  (%s)",name));
00913     return ret;
00914 }
00915 
00916 /**************** 
00917 
00918     Objectclasses 
00919 
00920 ****************/
00921 
00922 /*!
00923     LDAPOBJECT.oc_list
00924 
00925     Copy objectclass names to the list.
00926     Return number of items found.
00927 */
00928 PUBLIC int LDAPOBJECT::oc_list (SSTRINGS&lst)
00929 {
00930     int n =oclist.getnb();
00931 
00932     for (int i=0; i<n; i++){ 
00933         
00934         SSTRING *it = oclist.getitem(i);
00935         SSTRINGS tb;
00936         const char *name = NULL;
00937 
00938         str_splitline(it->get(),':',tb);
00939         name =  tb.getitem(1)->get();
00940         lst.add ( new SSTRING(name) );
00941         D(debugf(6,"LDAPOBJECT::oc_list %s",name));
00942     }   
00943 
00944     return n;
00945 }
00946 
00947 /*!
00948     LDAPOBJECT.oc_add
00949 
00950     Add named objectclass.
00951 */
00952 PUBLIC int LDAPOBJECT::oc_add (const char *val)
00953 {
00954     int ret=0;
00955     char buf[ATTR_VAL_MAX];
00956 
00957     snprintf(buf,sizeof(buf)-1,"objectClass: %s",val);
00958     oclist.add(new SSTRING (buf));
00959 
00960     // No objectclass need multivalues, 
00961     // so make sure there is only one of each
00962     oclist.remove_dups();
00963 
00964     D(debugf(4,"LDAPOBJECT::oc_add (%s)",buf));
00965     return ret;
00966 }
00967 
00968 /*!
00969     LDAPOBJECT.oc_del
00970 
00971     Delete named objectclass.
00972 */
00973 PUBLIC int LDAPOBJECT::oc_del (const char *name)
00974 {
00975     int ret=0;
00976 
00977     // Locate named class and remove it if found
00978     int n = oclist.lookup(name);
00979     if (n)
00980         ret = oclist.remove(oclist.getitem(n));
00981     else
00982         ret = -1;
00983 
00984     D(debugf(4,"---LDAPOBJECT::oc_del (%s)", name));
00985     return ret;
00986 }
00987 
00988 /*!
00989     LDAPOBJECT.oc_getval
00990 
00991     Return the name of objectclass n
00992     Return NULL if not found.
00993 */
00994 PUBLIC const char* LDAPOBJECT::oc_getval (int num)
00995 {
00996     SSTRINGS tb;
00997     const char *val = NULL;
00998 
00999     SSTRING *it = oclist.getitem(num);  
01000 
01001     if (it){        
01002         str_splitline(it->get(),':',tb);
01003         val = tb.getitem(1)->get();
01004     }
01005 
01006     // Remove frontspace
01007     str_skip(val);
01008 
01009     D(debugf(6,"LDAPOBJECT::oc_getval %s\n",val));
01010     return val;
01011 }
01012 
01013 /******************** 
01014 
01015     Utility functions 
01016 
01017 ********************/
01018 
01019 /*! 
01020     LDAPOBJECT.locateassign
01021     
01022     Lookup attribute and return in "raw" SSTRING format (name: value)
01023     Return NULL if not found.
01024 */
01025 PUBLIC SSTRING* LDAPOBJECT::locateassign (const char *key)
01026 {
01027     return LDAPOBJECT::locateassign (key,1);
01028 };
01029 
01030 /*!  
01031     LDAPOBJECT.locateassign
01032     
01033     Lookup attribute number k and return in "raw" SSTRING format (name: value)
01034     Return NULL if not found.
01035 
01036     k is >=1 and is the number of the attribute we are looking for
01037     1 means the first
01038     3 means the third....
01039     usefull for example if many mail attributes for the same person
01040 */
01041 PUBLIC SSTRING* LDAPOBJECT::locateassign (const char *key, int k)
01042 {
01043     int lenkey = strlen(key);
01044     int k2=0;
01045     SSTRING  *ret = NULL;
01046     int n = atlist.getnb();
01047     for (int i=0; i<n; i++){
01048         SSTRING *it = atlist.getitem (i);
01049         const char *pt = it->get();
01050         pt = str_skip(pt);
01051         if (strncasecmp(pt,key,lenkey)==0 && pt[lenkey] == ':'){ // 2.0
01052             k2++;
01053             if (k==k2) {    // k th attribute of value key, this is the good one 
01054                 ret = it;
01055                 break;
01056             }
01057         }
01058     }
01059     return ret;
01060 }
01061 
01062 /*!  
01063     LDAPOBJECT.locate
01064     
01065     Locate all attributes with the given name.
01066     Return number found.
01067 */
01068 PUBLIC int LDAPOBJECT::locate (const char *key, SSTRINGS &lst)
01069 {
01070     int lenkey = strlen(key);
01071     int ret = 0;
01072     int n = atlist.getnb();
01073     for (int i=0; i<n; i++){
01074         SSTRING *it = atlist.getitem (i);
01075         const char *pt = it->get();
01076         pt = str_skip(pt);
01077         if (strncasecmp(pt,key,lenkey)==0 && pt[lenkey] == ':'){
01078             // Strip the key
01079             pt += strlen(key)+1;
01080             pt = str_skip (pt);
01081             lst.add(new SSTRING (pt));
01082             ret++;
01083         }
01084     }
01085     return ret;
01086 }
01087 
01088 /*!  
01089     LDAPOBJECT.ldif_splitline
01090     
01091     Split ldif formatted stringline into attribute and value components.
01092 */
01093 PUBLIC int LDAPOBJECT::ldif_splitline (const char *ldif, char *name, char *val)
01094 { 
01095     char *pt;
01096 
01097     pt = strchr(ldif,':');
01098 
01099     if (pt != NULL) {
01100         // Extract name
01101         strncpy(name,ldif,ATTR_NAME_MAX);
01102         pt = strchr(name,':');
01103         *pt = '\0';
01104         strip_end(name);
01105         
01106         // Extract value
01107         pt = strchr(ldif,':');
01108         pt +=2;
01109         strncpy(val,pt,ATTR_VAL_MAX);
01110         strip_end(val);
01111         
01112         return 0;
01113     }
01114     else return -1;
01115 }
01116 
01117 
01118 /*************** 
01119 
01120    Utilities 
01121 
01122 ****************/
01123 
01124 /*!
01125 
01126     Load LDAP configuration from CONFDB profile object 
01127 
01128 */
01129 PUBLIC int LDAPOBJECT::load_profile(const char *profile_name)
01130 {
01131     D(debugf(4,"LDAPOBJECT::load_profile(%s)",profile_name));
01132 
01133     int ret = -1;
01134     
01135     CONFDB c_ldapconf(f_ldapconf);
01136 
01137     char fpath[PATH_MAX]; 
01138     /* Load profile */
01139     sprintf(fpath,"%s/%s",PROFILE_DIR,profile_name);
01140     CONFIG_FILE f_profile (fpath,help_ldap
01141                            ,CONFIGF_MANAGED|CONFIGF_OPTIONAL
01142                            ,"root","root",0600
01143                            ,subsys_ldap);   
01144     c_profile = new CONFDB (f_profile);
01145 
01146     this->bindname = c_profile->getval ("profile","bind","formclient");
01147     this->formname = c_profile->getval ("profile","form","formclient");
01148     this->dn_prefix = c_profile->getval ("profile","prefix","ou=People");
01149     this->group_prefix = c_profile->getval ("profile","groupprefix","ou=Group");
01150     this->primary_key = c_profile->getval ("profile","primarykey","uid");
01151     this->crypt_hash = c_profile->getval ("profile","crypt_hash","");
01152 
01153     /* Load binding */
01154     sprintf (fpath,"%s/%s",DBBIND_DIR,this->bindname.get());
01155     CONFIG_FILE f_bind (fpath,help_ldap
01156                         ,CONFIGF_MANAGED|CONFIGF_OPTIONAL
01157                         ,"root","root",0600
01158                         ,subsys_ldap);
01159     CONFDB c_bind (f_bind); 
01160 
01161     /* Set default binding */
01162     this->host = c_bind.getval("ldap","host");
01163     this->base = c_bind.getval("ldap","base");
01164     this->binddn = c_bind.getval("ldap","binddn");
01165     this->bindpw = c_bind.getval("ldap","bindpw");
01166 
01167     /* Load form */
01168     sprintf (fpath,"%s/%s",DBFORM_DIR,this->formname.get());
01169     CONFIG_FILE f_form (fpath,help_ldap
01170                         ,CONFIGF_MANAGED|CONFIGF_OPTIONAL
01171                         ,"root","root",0600
01172                         ,subsys_ldap);  
01173 
01174     if (this->form != NULL) delete this->form;
01175     this->form = new CONFDB(f_form);
01176 
01177     ret = 0;
01178     return ret;
01179 }
01180 
01181 /*!
01182 
01183     Set new password for the named user.
01184     Return error message if update failed.
01185     (normally caused by denied access)
01186 
01187 */
01188 PUBLIC int LDAPOBJECT::set_password (const char *username,const char *password)
01189 {
01190     int ret=0;
01191     SSTRINGS resmsg;
01192 
01193     command_line.setfrom("");
01194     if (!mode_openldap_version.cmp("2")) { // OpenLDAP 2.x
01195         command_line.appendf(" -s %s",password); //2.0 1.0= -e
01196         command_line.appendf(" uid=%s,%s,%s",username,dn_prefix.get(),base.get());
01197     }
01198     else { // OpenLDAP 1.x
01199         if (!crypt_hash.is_empty()) 
01200             command_line.appendf(" -H %s",crypt_hash.get());
01201         command_line.appendf(" -e %s",password);
01202         command_line.appendf(" -t uid=%s,%s,%s",username,dn_prefix.get(),base.get());
01203     }
01204 
01205     ret = command ("ldappasswd",resmsg); 
01206     
01207     return ret;
01208 }
01209 
01210 /*!
01211     LDAPOBJECT.export_confdb
01212   
01213     Export data to CONFDB object. 
01214 */
01215 PUBLIC int LDAPOBJECT::export_confdb(CONFDB *c_data)
01216 {
01217     int ret = 0;
01218     const char *prefix;
01219     const char *attr;
01220     SSTRING attrk;
01221     const char *val;
01222 
01223     SSTRINGS at_names;
01224 
01225     prefix = at_get(primary_key.get());
01226     int n = at_list(at_names); // Get all attribute names
01227 
01228     D(debugf(4,"LDAPOBJECT::export_confdb prefix=%s attrcount=%d\n",prefix,n));
01229 
01230     for (int i=0; i<n; i++){
01231         if (at_names.getitem(i)==NULL) continue;  //uncorrect result , let's try the next one
01232         attr = at_names.getitem(i)->get(); // Get attribute key
01233         const char * save_attr=attr;
01234         int k=0;
01235         c_data->removeall(prefix,attr);   // Reset item
01236         while (k++<1000) { // avoid infinite loop (should not happen !) 
01237             attr=save_attr;
01238             val = at_get(attr,k);                  // Get k  attribute value
01239             if (!val) break ; //exit the loop if no more value for this attribute
01240             if (k>1) { // multivalue attribute
01241                 // trick :
01242                 // we will use mail2 mail3   instead of mail
01243                 attrk.setfrom(attr);
01244                 attrk.appendf("%d",k);
01245                 attr=attrk.get(); // will be restored with save_attr
01246             }
01247             c_data->add(prefix,attr,val);     // Add item
01248             D(debugf(6,"LDAPOBJECT::export k=%d %s.%s=%s\n",k,prefix,attr,val));
01249         }
01250     }
01251     return ret;
01252 }
01253 
01254 /*! 
01255    LDAPOBJECT.import_confdb
01256 
01257    Import data from CONFDB object. 
01258 */
01259 PUBLIC int LDAPOBJECT::import_confdb(CONFDB *c_data)
01260 {
01261     D(debugf(4,"-->LDAPOBJECT::import_confdb"));
01262     int ret = 0;    
01263     const char *bkey;
01264     const char *key;
01265     const char *val;
01266 
01267     int n = c_data->getnb();
01268 
01269     // Reset/replace all existing attributes before import.
01270     atlist.remove_all();
01271 
01272     // Get all keys from confdb and register their data inside ldapobject 
01273     for (int i=0; i<n; i++){
01274         SSTRINGS tb;
01275 
01276         // Get the complet key
01277         const char *fullkey = c_data->getitem(i)->key.get(); // Get full key
01278 
01279         // Split key in minor and major
01280         str_splitline(fullkey,'.',tb);
01281         bkey = tb.getitem(0)->get();
01282         key = tb.getitem(1)->get();
01283         if (key == NULL)
01284             key = bkey;
01285         
01286         // Get the value
01287         val = c_data->getitem(i)->val.get(); 
01288 
01289         // Add attribute
01290         at_set(key,val); 
01291 
01292         D(debugf(4,":import_confdb: %s.%s=%s",bkey,key,val));
01293     }
01294 
01295     D(debugf(4,"<--LDAPOBJECT::import_confdb:"));
01296     return ret;
01297 }
01298 
01299 /*! 
01300     Return free uid to available for used by new object
01301 */
01302 PUBLIC int LDAPOBJECT::get_free_uid()
01303 {
01304     int uid = 999;
01305 
01306     return uid;
01307 }
01308 
01309 /*! 
01310     Return next free gid to be used by a new object
01311 */
01312 PUBLIC int LDAPOBJECT::get_free_gid()
01313 {
01314     int gid = 999;
01315 
01316     return gid;
01317 }
01318 
01319 
01320 /*~PROTOEND~ LDAPOBJECT */
01321 
01322 
01323 
01324 
01325 
01326 

Generated at Mon Jan 22 08:35:11 2001 for ldapconf by doxygen1.2.1 written by Dimitri van Heesch, © 1997-2000