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

useradmin.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 /*  USERADMIN.cc
00013 
00014     These dialogs are mainly designed to be used with account type 
00015     directories (like NIS/POSIX accounts).
00016 
00017 **************************************************************************/
00018 #include "ldapconf_defs.h"
00019 #include "fields.h"
00020 #include <subsys.h>
00021 #include <confdb.h>
00022 #include <string.h>
00023 #include <userconf.h>
00024 #include <stdlib.h>
00025 
00026 /*
00027 
00028   USERADMIN usermenu
00029 
00030 */
00031 void ldap_usermenu(const char *profile)
00032 {  
00033     const char *key_search = MSG_U(M_LDAP_PROFILE_SEARCH,"Search");
00034     const char *key_add = MSG_U(M_LDAP_PROFILE_ADDUSER,"Adduser");
00035     const char *key_list = MSG_U(M_LDAP_PROFILE_LIST,"Users");
00036     const char *key_groups = MSG_U(M_LDAP_PROFILE_GROUP,"Groups");
00037 
00038     DIALOG_MENU dia;
00039     int nof = 0;
00040     const char *key;
00041 
00042     dia.newf_info ("Profile",profile);  
00043     dia.new_menuitem("",key_search);
00044     dia.new_menuitem("",key_add);
00045     dia.new_menuitem("",key_list);
00046     dia.new_menuitem("",key_groups);
00047 
00048     while (1){ 
00049         MENU_STATUS code = dia.editmenu (MSG_U(T_PROFILE_USE,"Directory")
00050                                          ,MSG_U(I_PROFILE_USE,"Directory profile")
00051                                          ,help_formclient
00052                                          ,nof,0);
00053         key = dia.getmenustr(nof);
00054 
00055         if (code == MENU_ESCAPE || code == MENU_QUIT){
00056             break;
00057         }else if (key == key_search){
00058             ldap_form_search(profile);
00059         }else if (key == key_add){
00060             ldap_form_adduser(profile,NULL);
00061         }else if (key == key_list){
00062             ldap_userlist(profile);
00063         }else if (key == key_groups){
00064             ldap_groupadmin(profile);
00065         }
00066     }
00067 }
00068 
00069 /*
00070         Locate an attribute given its key in a SSTRING table
00071         expect a SSTRING to contain 
00072         var: =value
00073 */
00074 PUBLIC SSTRING * getldapattribute (SSTRINGS * atlist,const char *key)
00075 {
00076     if ((atlist==NULL) || (key==NULL)) return NULL;  //something is wrong, we're not going to find the attribute this way !
00077     int lenkey = strlen(key);
00078     SSTRING  *ret = NULL;
00079     int n = atlist->getnb();
00080     D(debugf(5,"getldapattribute n=%d, key=%s lenkey=%d\n",n,key,lenkey));
00081     for (int i=0; i<n; i++){
00082         SSTRING *it = atlist->getitem (i);
00083         const char *pt = it->get();
00084         D(debugf(7,"getldapattribute n=%d, key=%s lenkey=%d, trying match with %s\n",n,key,lenkey,pt));
00085         pt = str_skip(pt);
00086         if (strncasecmp(pt,key,lenkey)==0 && pt[lenkey] == ':'){ // 2.0
00087             ret= new SSTRING;   // will have to be freed
00088             ret->setfrom(pt+lenkey+2);
00089             D(debugf(6,"getldapattribute FOUND ! returning : %s\n",ret->get()));
00090             return ret;
00091             break;
00092         }
00093     }
00094     if (!ret) D(debugf(6,"getldapattribute attribute not found ! returning NULL (key=%s)",key));
00095     return ret;
00096 }
00097 
00098 /*
00099 
00100   LDAPCLIENT userlist
00101 
00102 */
00103 void ldap_userlist(const char *profile_name)
00104 {
00105     D(debugf(4,"-->USERADMIN::ldap_userlist (%s)",profile_name));
00106     SSTRING form_key;
00107     SSTRINGS user_list;
00108     LDAPOBJECT ldap(profile_name);
00109 
00110     DIALOG_RECORDS dia;
00111 
00112     ldap.filter.setfromf("%s=*",ldap.primary_key.get());
00113     int NB_USERLIST_ATNAME=3;
00114     const char *atname[NB_USERLIST_ATNAME+1];
00115 
00116     atname[0] = "cn";
00117     atname[1] = "uidnumber";
00118     atname[2] = "telephonenumber";
00119     atname[3] = NULL;
00120 
00121     dia.newf_head ("",MSG_U(H_USERS,"User\tName\tUID\tPhone"));
00122 // ie in ldap : uid\tcn\tuidNumber\ttelephoneNumber 
00123     SSTRING  *key;
00124     int MAX_DATA=2048;
00125     char data [2048];
00126 //  char *atlist;
00127     SSTRINGS tb;
00128     int nof = 0;
00129 
00130     while (1) {
00131         // Find all users
00132         user_list.remove_all();
00133         ldap.search_list_vals(user_list,ldap.primary_key.get(),atname);
00134         user_list.sort();
00135 
00136 // we're going through the user list 
00137         for (int i=0; i<user_list.getnb(); i++){
00138 // doing stuff for one user
00139 // resetting tb
00140             tb.remove_all();
00141             const char *line = user_list.getitem(i)->get();
00142 // line contains the list of attributes   attribute : value\tattribute2: value2....  
00143 // as we don't know the order, we have to look for value before we know which attribute to get
00144             str_splitline(line,'\t',tb);
00145 // tb is a table containing SSTRING of the form attribute: value
00146             D(debugf(6,"i=%d, userlist: %s\n",i,line));
00147 // looking for the attribute corresponding to uid
00148             key = getldapattribute(&tb,"uid");
00149             if (!key) { 
00150                 D(debugf(1,"i=%d, WARNING uid not found for user !!!\n",i));
00151                 continue ; // really bad ! it should not happen 
00152                 // we're going to the next user
00153             }
00154             D(debugf(6,"i=%d, key: %s\n",i,key->get()));
00155 //          char *pt = strchr(line,'\t');
00156 //          if (pt != NULL){
00157 //              strncpy(data,pt,sizeof(data));
00158 //          }
00159 // redondant            strncpy(data,key->get(),sizeof(data));
00160             strcpy(data,"");
00161             int ll=strlen(data);
00162             D(debugf(6,"i=%d, ll=%d,data = %s\n",i,ll,data));
00163             for (int k=0; k<=NB_USERLIST_ATNAME; k++) {
00164                 if (!atname[k]) continue;  //next one
00165                 ll=strlen(data);
00166                 D(debugf(6,"i=%d, k=%d, looking for supplemental attribute: %s\n",i,k,atname[k]));
00167                 SSTRING * attr=getldapattribute(&tb,atname[k]); 
00168                 if (!attr) {
00169                     // ok attribute not present
00170                     D(debugf(6,"i=%d, k=%d, attribute not found\n",i,k));
00171                     strncat(data,"\t",MAX_DATA-ll);
00172                     continue; // going to next attribute
00173                 }
00174                 // we have the attribute content in attr
00175                 D(debugf(6,"i=%d, k=%d, attribute found\n",i,k));
00176                 strncat(data,attr->get(),MAX_DATA-ll);
00177                 strncat(data,"\t",MAX_DATA-ll-1);
00178                 D(debugf(6,"i=%d, ik=%d, data = %s\n",i,k,data));
00179 // delete attr
00180             }
00181 // ok we have all the values added to data 
00182             D(debugf(4,"i=%d, setting entry menu %s\n",i,data));
00183             dia.set_menuitem (i,key->get(),data);
00184 //          char * atlist;
00185 //          atlist = strchr(line,':'); // 2.x, should work for 1.x also
00186 //          if (atlist != NULL){
00187 //              *atlist = '\0';
00188 //              atlist++;
00189 //              dia.set_menuitem (i,key->get(),atlist);
00190 //              debugf(4,"i=%d, userkey: %s userline: %s\n",i,key,atlist);
00191 //          }
00192 //          } else {
00193 //          debugf(4,"i=%d, userkey: %s userline: %s\n",i,key,data);
00194 // 1.x          dia.set_menuitem (i,key,data);
00195 // going to next user
00196             D(debugf(6,"i=%d, going to next user\n",i));
00197         }
00198         D(debugf(7,"removing last entry \n"));
00199         dia.remove_last(user_list.getnb()+1);
00200         
00201         MENU_STATUS code = dia.editmenu (MSG_U(T_USER_LIST,"User list")
00202                                          ,MSG_U(I_USER_LIST,"Select user")              
00203                                          ,help_groupadmin
00204                                          ,nof
00205                                          ,MENUBUT_ADD);
00206 
00207         if (code == MENU_QUIT || code == MENU_ESCAPE){ /* Exit */
00208             break;
00209         }
00210         else if (code == MENU_ADD ){ /* Add a new entry */          
00211             ldap_form_adduser(profile_name,NULL);
00212         } else if (nof >=0 && nof < user_list.getnb()){ /* Edit selected entry */
00213             const char *line;
00214             line = user_list.getitem(nof)->get();
00215             char *pt;
00216             pt = strchr(line,'\t'); // 2.x
00217             if (pt != NULL){
00218                 *pt = '\0';
00219             }
00220             // line now contains uid entry, now extract the uid name
00221             char name[ATTR_NAME_MAX];
00222             char val[ATTR_VAL_MAX];
00223             ldap.ldif_splitline(line,name,val);
00224             ldap_form_edituser(profile_name,val);
00225         }
00226     }
00227     D(debugf(4,"<--USERADMIN::ldap_userlist"));
00228 }
00229 
00230 /*!
00231 
00232   LDAPCLIENT edituser
00233 
00234 */
00235 void ldap_form_edituser(const char *profile_name,const char *user_name)
00236 {
00237     SSTRING form_key;
00238     LDAPOBJECT ldap(profile_name);
00239     CONFDB ldapdb;
00240     int nof = 0;
00241 
00242     form_key.setfrom(user_name);
00243 
00244     FIELD_DEFS defs(ldap.form);
00245 
00246     DIALOG dia;
00247     dia.newf_title ("Userform",0,"","Userform");
00248     dia.newf_info ("Profile",profile_name);
00249     dia.newf_info (MSG_U(I_FORM_DATA,"Form"),ldap.formname.get());
00250     dia.newf_info (MSG_U(I_FORM_KEY,"Userkey"),form_key.get());
00251 
00252     /* Extra buttons */
00253     dia.setbutinfo (MENU_USR1,MSG_U(B_PASSWORD,"Passwd"),MSG_U(X_PASSWORD,"Passwd"));
00254     
00255     /* Read form fields */
00256     defs.read();
00257    
00258     /* Lookup field data */ 
00259     ldap.filter.setfromf("%s=%s",ldap.primary_key.get(),user_name);
00260     ldap.search();
00261     ldap.export_confdb(&ldapdb);
00262 
00263     /* Load field data */
00264     defs.loadval (&ldapdb,form_key.get());
00265     
00266     /* Draw form */
00267     defs.setupdia(dia); 
00268 
00269     while (1) {
00270         dia.reload();
00271 
00272         MENU_STATUS code = dia.edit (MSG_U(T_FORM_CLIENT,"User")
00273                                      ,MSG_U(I_FORM_CLIENT,"This form will update userdata in the LDAP directory")               
00274                                      ,help_formclient
00275                                      ,nof
00276                                      ,MENUBUT_USR1|MENUBUT_ACCEPT|MENUBUT_QUIT|MENUBUT_DEL);
00277         // Save dialog entries
00278         //dia.save();
00279 
00280         if (code == MENU_CANCEL || code == MENU_QUIT || code == MENU_ESCAPE){ /* Exit */
00281             break;
00282         } else if (code == MENU_ACCEPT){ /* Update */
00283             /* Check if this entry exist */
00284             ldap.filter.setfromf("%s=%s",ldap.primary_key.get(),form_key.get());
00285             int n = ldap.search();
00286             if ( n == 1) {
00287                 defs.saveval (&ldapdb,form_key.get());
00288                 ldap.import_confdb(&ldapdb);
00289                 ldap.modify();
00290                 break;
00291             }
00292         } else if (code == MENU_DEL){ /* Delete */
00293             if (dialog_yesno("Delete user","Delete user from directory?",help_formclient) == MENU_YES) {        
00294                 ldap.del();
00295                 logf(LOG_NOTICE,"Deleting user %s from directory %s",user_name,profile_name);
00296                 break;
00297             }
00298         }
00299         else if (code == MENU_USR1){
00300             ldap_form_password(form_key.get(),profile_name);
00301         }
00302     }
00303 }
00304 
00305 /*
00306 
00307   LDAPCLIENT adduser
00308 
00309 */
00310 void ldap_form_adduser(const char *profile_name,const char *user_name)
00311 {
00312     SSTRING user; // for example pdupond
00313     SSTRING firstname; // optional example Patrick
00314     SSTRING lastname; // optional example Dupond
00315     SSTRING firstpluslast; // computed from fistname+lastname
00316     LDAPOBJECT ldap(profile_name);
00317     int nof;
00318 
00319     FIELD_DEFS defs(ldap.form); //to get default value
00320     defs.read();  // fill the structure with values
00321 
00322     DIALOG dia;
00323     dia.newf_info (MSG_U(I_PROFILE,"Profile"),profile_name);
00324     dia.newf_info (MSG_R(I_FORM_DATA),ldap.formname.get());
00325     dia.newf_str (MSG_R(F_USERNAME),user);
00326     dia.newf_title (MSG_U(I_OPTIONAL,"Optional"),1,"",MSG_R(I_OPTIONAL));
00327     dia.newf_str (MSG_R(F_GIVENNAME),firstname);    
00328     dia.newf_str (MSG_R(F_SN),lastname);    
00329 //! \todo password at the same time
00330 //! \todo add here a list with choices which would change the defaults
00331 //! very useful to handle multiple domain on the same machine for example
00332     
00333     while (1) {
00334         MENU_STATUS code = dia.edit (MSG_U(T_ADD_USER,"User")
00335                                      ,MSG_U(I_ADD_USER,"Add user")              
00336                                      ,help_formclient
00337                                      ,nof
00338                                      ,MENUBUT_ACCEPT|MENUBUT_QUIT);
00339    
00340         // Save dialog entries
00341         dia.save();
00342 
00343         if (code == MENU_CANCEL || code == MENU_QUIT || code == MENU_ESCAPE){ /* Exit */
00344             break;
00345         } else if (code == MENU_ACCEPT){ /* Add new entry */    
00346             /* Check that new name is specified */
00347             if (user.is_empty()){
00348 // FIXME translation
00349                 xconf_error("Account name not specified");
00350             } else {
00351                 /* Check if this entry exist */         
00352                 ldap.filter.setfromf("%s=%s",ldap.primary_key.get(),user.get());
00353                 int n = ldap.search();
00354                 if (n==0) { /* Add new entry */
00355                     ldap.dn.setfromf("dn: %s=%s,%s,%s",
00356                                      ldap.primary_key.get(),
00357                                      user.get(),
00358                                      ldap.dn_prefix.get(),
00359                                      ldap.base.get());
00360 
00361                     /* 
00362                        Now add a generic set of required attributes and classes, 
00363                        so the new objects will be accepted in the directory. 
00364                        We need a way to let the user customize this instead 
00365                        of hardcoding it. Some kind of template, or maybe it is 
00366                        possible to use the existing schema files in some way.
00367                        Maybe the classes could be specified with the formfield 
00368                        system.
00369                        Note : start of this with support for default parameter in form
00370                     */
00371 
00372                     // we will need this latter
00373                     firstpluslast.setfrom(firstname);
00374                     if (firstpluslast.getlen()>1) {
00375                         firstpluslast.append(" ");
00376                     }
00377                     firstpluslast.append(lastname.get());
00378                     if (firstpluslast.getlen()<3) { // user was lazy
00379                         firstpluslast.setfrom(user); // can't be empty
00380                     }
00381                     // Often needed
00382                     ldap.oc_add("top");
00383 
00384                     // nis account
00385                     ldap.oc_add("posixAccount");
00386                     ldap.oc_add("posixGroup");
00387                     ldap.oc_add("account");
00388                 
00389                     ldap.at_set("uid",user.get());
00390                     ldap.at_set("cn",firstpluslast.get());
00391                     // Request free uidnumber
00392                     ldap.at_set("uidNumber",ldap_get_free_uidnumber(profile_name));
00393                     // Set to uidbumber for now
00394                     ldap.at_set("gidNumber",ldap.at_get("uidNumber"));
00395                     // Defaults (mostly taken from form)
00396                     // home directory
00397                     SSTRING * temphome;
00398                     temphome =defs.getdefault("homedirectory");
00399                     if (temphome) {
00400                         ldap.at_set("homeDirectory",temphome->get());
00401                     } else {
00402                         ldap.at_set("homeDirectory","/home/ldapuser"); // Needed for NIS schema  
00403                     }
00404                     
00405                     // login shell
00406                     SSTRING * templogin;
00407                     templogin =defs.getdefault("loginShell");
00408                     if (templogin) {
00409                         ldap.at_set("loginShell",templogin->get());
00410                     } else {
00411                         ldap.at_set("loginShell","/bin/false"); // Needed for NIS schema  
00412                     }
00413 
00414                     // Gecos
00415                     SSTRING * tempgecos;
00416                     tempgecos =defs.getdefault("Gecos");
00417                     if (tempgecos) {
00418                         ldap.at_set("Gecos",tempgecos->get());
00419                     } else {
00420                         ldap.at_set("Gecos",firstpluslast.get());
00421                     }
00422                     // Host login access (MULTI)
00423                     //ldap.at_add("host","localhost");
00424 
00425                     // person
00426                     ldap.oc_add("person");
00427                     ldap.oc_add("organizationalPerson");
00428                     ldap.oc_add("inetOrgPerson");
00429 
00430                     // sn
00431                     SSTRING * tempsn;
00432                     tempsn =defs.getdefault("sn");
00433                     if (lastname.getlen()>0) {
00434                         ldap.at_set("sn",lastname.get());
00435                     } else if (tempsn) {
00436                         ldap.at_set("sn",tempsn->get());
00437                     };
00438 
00439                     // givenName
00440                     SSTRING * tempgivenname;
00441                     tempgivenname =defs.getdefault("givenName");
00442                     if (firstname.getlen()>0) {
00443                         ldap.at_set("givenName",firstname.get());
00444                     } else if (tempgivenname) {
00445                         ldap.at_set("givenName",tempgivenname->get());
00446                     }
00447 
00448                     // organization
00449                     SSTRING * temporga;
00450                     temporga =defs.getdefault("ou");
00451                     if (temporga) {
00452                         ldap.at_set("ou",temporga->get());
00453                     }
00454 
00455                     // mail
00456                     ldap.oc_add("inetLocalMailRecipient");
00457 
00458                     // mail accounts (MULTI)
00459                     SSTRING tempmail;
00460                     SSTRING * tempdomain;
00461                     tempdomain =defs.getdefault("mail");
00462                     if (tempdomain) {
00463                         // user@domain.com ie pdupond@domain.com
00464                         tempmail.setfrom(user.get());
00465                         tempmail.append("@");
00466                         tempmail.append(tempdomain->get());
00467                         tempmail.to_lower();
00468                         ldap.at_add("mail",tempmail.get());
00469                         // firstname.lastname@domain.com
00470                         tempmail.setfrom(firstname.get());
00471                         tempmail.append(".");
00472                         tempmail.append(lastname.get());
00473                         tempmail.append("@");
00474                         tempmail.append(tempdomain->get());
00475                         tempmail.to_lower();
00476                         ldap.at_add("mail",tempmail.get());
00477                         SSTRING firstname2(firstname);
00478                         firstname2.truncate(1); // we only wan't the first letter to make p.dupond
00479                         tempmail.setfrom(firstname2.get());
00480                         tempmail.append(".");
00481                         tempmail.append(lastname.get());
00482                         tempmail.append("@");
00483                         tempmail.append(tempdomain->get());
00484                         tempmail.to_lower();
00485                         ldap.at_add("mail",tempmail.get());
00486                     }
00487 
00488                     // Add account to directory
00489                     ldap.add();
00490 //  FIXME : this is not coherent with the userinterface
00491 // because the user is added before the user says accept and if he cancels,
00492 // it is naturel to think that the user was not added ! 
00493                     // Customize account FIXME: It should be possible to custmoize before adding to dir. Need editdialog for CONFDB
00494                     ldap_form_edituser(profile_name,user.get());
00495                     logf(LOG_NOTICE,"Adding user %s to directory %s",user.get(),profile_name);
00496 
00497                     break;
00498                 }
00499                 else { 
00500 //FIXME : translation
00501                     xconf_error("Account already in use"); 
00502                 }
00503             }
00504         }
00505     }
00506 }
00507 
00508 /*
00509 
00510   LDAPCLIENT search
00511 
00512 */
00513 void ldap_form_search(const char *profile_name)
00514 {
00515     SSTRING form_key;
00516     LDAPOBJECT ldap(profile_name);
00517     int nof = 0;
00518 
00519     DIALOG dia;
00520     dia.newf_info ("Profile",profile_name);
00521 
00522 //  dia.newf_title(MSG_U(F_SEARCH_FORM,"Search"),1,"",MSG_R(F_SEARCH_FORM));
00523     dia.newf_str (MSG_U(F_SEARCH_KEY,"Search key"),form_key);
00524     
00525     /* Extra buttons */
00526     dia.setbutinfo (MENU_USR1,MSG_R(B_SEARCH),MSG_R(X_SEARCH));
00527 
00528     
00529     while (1) {
00530         MENU_STATUS code = dia.edit (MSG_U(T_FORM_SEARCH,"Search")
00531                                      ,MSG_U(I_FORM_SEARCH,"Search directory")               
00532                                      ,help_formclient
00533                                      ,nof
00534                                      ,MENUBUT_USR1|MENUBUT_QUIT);
00535    
00536         // Save dialog entries
00537         dia.save();
00538 
00539         /* Refresh dialog */
00540         if (code == MENU_CANCEL || code == MENU_QUIT || code == MENU_ESCAPE){ /* Exit */
00541             break;
00542         } else if (code == MENU_USR1 || code == MENU_ACCEPT){ /* Search */
00543             SSTRINGS dnlist;
00544             D(debugf(4,"search : key =%s , formkey=%s \n",ldap.primary_key.get(),form_key.get()));
00545             ldap.filter.setfromf("%s=%s",ldap.primary_key.get(),form_key.get());
00546             int n = ldap.search_list_val(dnlist,ldap.primary_key.get());
00547             D(debugf(6,"fin search : n=%d\n",n));
00548             if (n > 1) { // Multiple results
00549                 SSTRING choice;
00550                 ldaplist(dnlist,choice);
00551                 ldap.base.setfromf("%s,%s",ldap.dn_prefix.get(),ldap.base.get());
00552                 ldap.filter.setfromf("%s=%s",ldap.primary_key.get(),choice.get());
00553                 ldap.search();
00554             }
00555             ldap.search();
00556             form_key.setfrom(ldap.at_get(ldap.primary_key.get()));
00557             ldap_form_edituser(profile_name,form_key.get());    
00558         }
00559     }
00560 }
00561 
00562 /*
00563 
00564   LDAPCLIENT password sync
00565 
00566 */
00567 int ldap_pwsync(const char *username, const char *domain, const char *new_password)
00568 {
00569     int ret = -1;
00570     const char *profile_name;
00571 
00572     // Lookup domain profile
00573     char fpath[PATH_MAX]; 
00574     sprintf(fpath,"%s/%s",PROFILE_DIR,domain);
00575 
00576     if (!strcmp(domain,"/")) { // Maindomain profile
00577         profile_name = "userinfo";
00578         D(debugf(4,"ldap_pwsync: main domain: %s\n",domain));
00579     }
00580     else if (fopen(fpath,"r")){ // Virtual domain profile
00581         profile_name = domain;
00582         D(debugf(4,"ldap_pwsync: virtual domain: %s\n",domain));
00583     }
00584     else { // No profile
00585         D(debugf(4,"ldap_pwsync: no profile: %s\n",domain));
00586         return ret;
00587     }
00588 
00589     LDAPOBJECT ldap(profile_name);
00590 
00591     if (ldap.c_profile->getvalnum("profile","userinfo_comng",0)) 
00592         ret = ldap.set_password(username,new_password);
00593 
00594     return ret;
00595 }
00596 
00597 /*
00598 
00599   LDAPCLIENT password
00600 
00601 */
00602 void ldap_form_password(const char*user_name,const char *profile_name)
00603 {
00604     SSTRING password;
00605     LDAPOBJECT ldap(profile_name);
00606     int nof = 0;
00607 
00608     DIALOG dia;
00609     dia.newf_info ("Profile",profile_name);
00610     dia.newf_info ("User",user_name);
00611 
00612     dia.newf_pass (MSG_U(F_PASSWORD,"Password"),password);
00613     
00614     while (1) {
00615         MENU_STATUS code = dia.edit (MSG_U(T_FORM_PASSWORD,"Password")
00616                                      ,MSG_U(I_FORM_PASSWORD,"Enter new password")               
00617                                      ,help_formclient
00618                                      ,nof
00619                                      ,MENUBUT_ACCEPT|MENUBUT_QUIT);
00620    
00621         // Save dialog entries
00622         dia.save();
00623 
00624         /* Refresh dialog */
00625         if (code == MENU_CANCEL || code == MENU_QUIT || code == MENU_ESCAPE){ /* Exit */
00626             break;
00627         } else if (code == MENU_ACCEPT){ /* Change password */
00628             if (ldap.set_password(user_name,password.get())) {
00629                 xconf_error("Password not changed");
00630             }   
00631             else {
00632                 xconf_notice("Password changed");
00633                 break;
00634             }
00635         }
00636     }
00637 }
00638 
00639 
00640 /*
00641 
00642   Migrate users from system password files to ldap directory.
00643 
00644 */
00645 int ldap_migrate_users(const char *profile_name){
00646     int ret = -1;
00647     int i;
00648     USERS users;
00649     GROUPS groups;
00650     LDAPOBJECT ldap(profile_name);
00651     char buf[256]; 
00652     char ignore_admin = true;
00653     char ignore_special = true;
00654     
00655     int nof;
00656     DIALOG dia;
00657     dia.newf_chk ("Admin accounts",ignore_admin,"Ignore");
00658     dia.newf_chk ("Special accounts",ignore_special,"Ignore");
00659 
00660     while (1){
00661         MENU_STATUS code = dia.edit (MSG_U(T_MIGRATE,"Migrate")
00662                                      ,MSG_U(I_MIGRATE
00663                                             ,"This will import users from the local system files")
00664                                      ,help_ldap         
00665                                      ,nof);
00666         if (code == MENU_CANCEL || code == MENU_ESCAPE){
00667             break;
00668         }
00669         else if (code == MENU_ACCEPT &&
00670                  xconf_yesno(MSG_U(T_MIGRATE_OK,"LDAP user migration"),
00671                              MSG_U(I_MIGRATE_OK,
00672                                    "This will migrate all user data\n"
00673                                    "from the localhost into this LDAP directory\n"
00674                                    "This is usually only done when installing a new LDAP system.\n"
00675                                    "Are you sure you want to do this?\n"),
00676                              help_ldap) == MENU_YES)
00677             {
00678                 int n=0; // Count migrated accounts
00679                 for (i=0;i<users.getnb();i++){
00680                     USER *user = users.getitem(i);
00681                     
00682                     // Ignore system accounts
00683                     if ((ignore_admin==true && !user->is_admin()) || 
00684                         (ignore_special==true && !user->is_special()))
00685                         {
00686                             D(debugf(5,"ignore user (%s)",user->getname()));
00687                             continue;
00688                         }
00689 
00690                     ldap.reset_data();
00691                     
00692                     ldap.dn.setfromf("dn: %s=%s,%s,%s",
00693                                      ldap.primary_key.get(),
00694                                      user->getname(),
00695                                      ldap.dn_prefix.get(),
00696                                      ldap.base.get());
00697                 
00698                     /* Check if this entry exist */         
00699 //                  ldap.filter.setfromf("%s=%s",ldap.primary_key.get(),user->getname());
00700 //                  int n = ldap.search();
00701 //                  if ( n < 1) { /* Add new entry */
00702                     ldap.at_set("uid",user->getname());
00703                     ldap.at_set("cn",user->getname());
00704                     ldap.at_set("sn",user->getname());
00705                     ldap.at_set("uidNumber",user->getuid());
00706                     ldap.at_set("gidNumber",user->getgid());
00707                     ldap.at_set("homeDirectory",user->gethome()); 
00708                     ldap.at_set("loginShell",user->getshell());
00709                     ldap.at_set("GECOS",user->getgecos());
00710                     sprintf(buf,"{crypt}%s",user->getpwd());
00711 // FIXME: Something was broken here after the base64 password hack...
00712 //                  ldap.at_set("userPassword",buf);
00713                     
00714                     ldap.oc_add("top");
00715                     ldap.oc_add("account");
00716                     ldap.oc_add("posixAccount");
00717                     ldap.oc_add("inetLocalMailRecipient");
00718                     ldap.oc_add("organizationalPerson");
00719                     ldap.oc_add("inetOrgPerson");   
00720                     
00721                     ldap.add();
00722                     
00723                     n++;
00724                     D(debugf(4,":migrate: (%s) %i",ldap.dn.get(),n));
00725 //                  }
00726                 }
00727                 xconf_notice("Migrated %d user accounts.",n);
00728                 logf(LOG_NORMAL,"Migrated %d users using profile %s",profile_name);
00729                 ret = i;
00730             }
00731     }
00732     return ret;
00733 }
00734 
00735 /*  
00736   Determine the next free uidnumber available for a new account.
00737   Return the free uidnumber if it is available.
00738   Return -1 if it could not be determined, for some reason.
00739 
00740   This is first attempt to implement a usable method for locating free uids.
00741   The principle is simple: Locate the highest uid in use by the directory, 
00742   increment it by one, and return the result. Also reserve a range in the top and the bottom 
00743   of the uid range (or rather, define the range available).
00744 
00745   This method is pretty slow and weak, but should hopefully work for small directories.
00746 */
00747 int ldap_get_free_uidnumber(const char *profile_name){
00748     LDAPOBJECT ldap(profile_name);
00749     SSTRINGS uidnumbers;
00750     int free_uid;
00751 
00752     ldap.filter.setfromf("%s=*",ldap.primary_key.get());
00753     ldap.search_list_val(uidnumbers,"uidNumber"); // Returns a list with the currently used uidnumbers
00754     int min_uid,  // The minimum uid number available
00755         max_uid,  // The maximum uid number available
00756         top_uid,  // The highest uid number in use
00757         top_idx,  // The list index of the highest number
00758         cur_uid;  // The current uid found in the list
00759     
00760     min_uid = ldap.c_profile->getvalnum("profile","min_uid",10000); // Set uid range
00761     max_uid = ldap.c_profile->getvalnum("profile","max_uid",50000);
00762 
00763     top_uid = min_uid - 1; // Start just below the valid uid range
00764     D(debugf(5,"maxuid=%i minuid=%i top_uid=%i",max_uid,min_uid,top_uid));
00765 
00766     for (int i=0; i<uidnumbers.getnb(); i++){
00767         cur_uid = uidnumbers.getitem(i)->getval();
00768         // Compare and range check
00769         if (cur_uid > top_uid &&
00770             cur_uid >= min_uid &&
00771             cur_uid < max_uid)
00772             { // This was higher and valid
00773                 top_uid = cur_uid;
00774                 top_idx = i;
00775             }
00776     }
00777 
00778     free_uid = top_uid + 1 ; // Let's try with the next uid and range check it below
00779 
00780     if (free_uid < min_uid || free_uid >= max_uid) { // Not valid - log it for now, make a popup error later
00781         free_uid = -1;
00782         logf(LOG_ERROR,"No uidnumber available for new account (min=%i, max=%i, top=%i)",
00783              min_uid,max_uid,top_uid);
00784     }
00785 
00786     // here we should also check if the uid exist in the directory by doing a lookup - coming later
00787     D(debugf(4,"<--useradmin::ldap_get_free_uid return freeuid = %i",free_uid));
00788     return free_uid;
00789 }
00790 

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