Changes from APPLIANCE_HEAD:
[ira/wip.git] / source3 / passdb / ldap.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    LDAP protocol helper functions for SAMBA
5    Copyright (C) Jean Fran├žois Micouleau 1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21 */
22
23 #ifdef WITH_LDAP
24
25 #include "includes.h"
26
27 #include <lber.h>
28 #include <ldap.h>
29
30 #define ADD_USER 1
31 #define MODIFY_USER 2
32
33 extern int DEBUGLEVEL;
34
35 /*******************************************************************
36  open a connection to the ldap serve.
37 ******************************************************************/     
38 static BOOL ldap_open_connection(LDAP **ldap_struct)
39 {
40         if ( (*ldap_struct = ldap_open(lp_ldap_server(),lp_ldap_port()) ) == NULL)
41         {
42                 DEBUG( 0, ( "The LDAP server is not responding !\n" ) );
43                 return( False );
44         }
45         DEBUG(2,("ldap_open_connection: connection opened\n"));
46         return (True);
47 }
48
49
50 /*******************************************************************
51  connect anonymously to the ldap server.
52  FIXME: later (jfm)
53 ******************************************************************/     
54 static BOOL ldap_connect_anonymous(LDAP *ldap_struct)
55 {
56         if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) ! = LDAP_SUCCESS)
57         {
58                 DEBUG( 0, ( "Couldn't bind to the LDAP server !\n" ) );
59                 return(False);
60         }
61         return (True);
62 }
63
64
65 /*******************************************************************
66  connect to the ldap server under system privileg.
67 ******************************************************************/     
68 static BOOL ldap_connect_system(LDAP *ldap_struct)
69 {
70         if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) ! = LDAP_SUCCESS)
71         {
72                 DEBUG( 0, ( "Couldn't bind to the LDAP server!\n" ) );
73                 return(False);
74         }
75         DEBUG(2,("ldap_connect_system: succesful connection to the LDAP server\n"));
76         return (True);
77 }
78
79 /*******************************************************************
80  connect to the ldap server under a particular user.
81 ******************************************************************/     
82 static BOOL ldap_connect_user(LDAP *ldap_struct, char *user, char *password)
83 {
84         if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) ! = LDAP_SUCCESS)
85         {
86                 DEBUG( 0, ( "Couldn't bind to the LDAP server !\n" ) );
87                 return(False);
88         }
89         DEBUG(2,("ldap_connect_user: succesful connection to the LDAP server\n"));
90         return (True);
91 }
92
93 /*******************************************************************
94  run the search by name.
95 ******************************************************************/     
96 static BOOL ldap_search_one_user(LDAP *ldap_struct, char *filter, LDAPMessage **result)
97 {       
98         int scope = LDAP_SCOPE_ONELEVEL;
99         int rc;
100                 
101         DEBUG(2,("ldap_search_one_user: searching for:[%s]\n", filter));
102                 
103         rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, result);
104
105         if (rc ! = LDAP_SUCCESS )
106         {
107                 DEBUG( 0, ( "Problem during the LDAP search\n" ) );
108                 return(False);
109         }
110         return (True);
111 }
112
113 /*******************************************************************
114  run the search by name.
115 ******************************************************************/     
116 static BOOL ldap_search_one_user_by_name(LDAP *ldap_struct, char *user, LDAPMessage **result)
117 {       
118         pstring filter;
119         /*
120            in the filter expression, replace %u with the real name
121            so in ldap filter, %u MUST exist :-)
122         */      
123         pstrcpy(filter,lp_ldap_filter());
124         pstring_sub(filter,"%u",user);
125         
126         if ( !ldap_search_one_user(ldap_struct, filter, result) )
127         {
128                 return(False);
129         }
130         return (True);
131 }
132
133 /*******************************************************************
134  run the search by uid.
135 ******************************************************************/     
136 static BOOL ldap_search_one_user_by_uid(LDAP *ldap_struct, int uid, LDAPMessage **result)
137 {       
138         pstring filter;
139         
140         slprintf(filter, sizeof(pstring)-1, "uidAccount = %d", uid);
141         
142         if ( !ldap_search_one_user(ldap_struct, filter, result) )
143         {       
144                 return(False);
145         }
146         return (True);
147 }
148
149 /*******************************************************************
150  search an attribute and return the first value found.
151 ******************************************************************/
152 static void get_single_attribute(LDAP *ldap_struct, LDAPMessage *entry, char *attribute, char *value)
153 {
154         char **valeurs;
155         
156         if ( (valeurs = ldap_get_values(ldap_struct, entry, attribute)) ! = NULL) 
157         {
158                 pstrcpy(value, valeurs[0]);
159                 ldap_value_free(valeurs);
160                 DEBUG(3,("get_single_attribute: [%s] = [%s]\n", attribute, value));     
161         }
162         else
163         {
164                 value = NULL;
165         }
166 }
167
168 /*******************************************************************
169  check if the returned entry is a sambaAccount objectclass.
170 ******************************************************************/     
171 static BOOL ldap_check_user(LDAP *ldap_struct, LDAPMessage *entry)
172 {
173         BOOL sambaAccount = False;
174         char **valeur;
175         int i;
176
177         DEBUG(2,("ldap_check_user: "));
178         valeur = ldap_get_values(ldap_struct, entry, "objectclass");
179         if (valeur! = NULL)
180         {
181                 for (i = 0;valeur[i]! = NULL;i++)
182                 {
183                         if (!strcmp(valeur[i],"sambaAccount")) sambaAccount = True;
184                 }
185         }
186         DEBUG(2,("%s\n",sambaAccount?"yes":"no"));
187         ldap_value_free(valeur);
188         return (sambaAccount);
189 }
190
191 /*******************************************************************
192  check if the returned entry is a sambaTrust objectclass.
193 ******************************************************************/     
194 static BOOL ldap_check_trust(LDAP *ldap_struct, LDAPMessage *entry)
195 {
196         BOOL sambaTrust = False;
197         char **valeur;
198         int i;
199         
200         DEBUG(2,("ldap_check_trust: "));
201         valeur = ldap_get_values(ldap_struct, entry, "objectclass");
202         if (valeur! = NULL)
203         {
204                 for (i = 0;valeur[i]! = NULL;i++)
205                 {
206                         if (!strcmp(valeur[i],"sambaTrust")) sambaTrust = True;
207                 }
208         }       
209         DEBUG(2,("%s\n",sambaTrust?"yes":"no"));
210         ldap_value_free(valeur);        
211         return (sambaTrust);
212 }
213
214 /*******************************************************************
215  retrieve the user's info and contruct a smb_passwd structure.
216 ******************************************************************/
217 static void ldap_get_smb_passwd(LDAP *ldap_struct,LDAPMessage *entry, 
218                           struct smb_passwd *user)
219 {       
220         static pstring user_name;
221         static pstring user_pass;
222         static pstring temp;
223         static unsigned char smblmpwd[16];
224         static unsigned char smbntpwd[16];
225
226         pdb_init_smb(user);
227
228         memset((char *)smblmpwd, '\0', sizeof(smblmpwd));
229         memset((char *)smbntpwd, '\0', sizeof(smbntpwd));
230
231         get_single_attribute(ldap_struct, entry, "cn", user_name);
232         DEBUG(2,("ldap_get_smb_passwd: user: %s\n",user_name));
233                 
234 #ifdef LDAP_PLAINTEXT_PASSWORD
235         get_single_attribute(ldap_struct, entry, "userPassword", temp);
236         nt_lm_owf_gen(temp, user->smb_nt_passwd, user->smb_passwd);
237         memset((char *)temp, '\0', sizeof(temp)); /* destroy local copy of the password */
238 #else
239         get_single_attribute(ldap_struct, entry, "unicodePwd", temp);
240         pdb_gethexpwd(temp, smbntpwd);          
241         memset((char *)temp, '\0', sizeof(temp)); /* destroy local copy of the password */
242
243         get_single_attribute(ldap_struct, entry, "dBCSPwd", temp);
244         pdb_gethexpwd(temp, smblmpwd);          
245         memset((char *)temp, '\0', sizeof(temp)); /* destroy local copy of the password */
246 #endif
247         
248         get_single_attribute(ldap_struct, entry, "userAccountControl", temp);
249         user->acct_ctrl = pdb_decode_acct_ctrl(temp);
250
251         get_single_attribute(ldap_struct, entry, "pwdLastSet", temp);
252         user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
253
254         get_single_attribute(ldap_struct, entry, "rid", temp);
255
256         /* the smb (unix) ids are not stored: they are created */
257         user->smb_userid = pdb_user_rid_to_uid (atoi(temp));
258
259         if (user->acct_ctrl & (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST) )
260         {
261                 DEBUG(0,("Inconsistency in the LDAP database\n"));
262         }
263         if (user->acct_ctrl & ACB_NORMAL)
264         {
265                 user->smb_name      = user_name;
266                 user->smb_passwd    = smblmpwd;
267                 user->smb_nt_passwd = smbntpwd;
268         }
269 }
270
271 /*******************************************************************
272  retrieve the user's info and contruct a sam_passwd structure.
273
274  calls ldap_get_smb_passwd function first, though, to save code duplication.
275
276 ******************************************************************/
277 static void ldap_get_sam_passwd(LDAP *ldap_struct, LDAPMessage *entry, 
278                           struct sam_passwd *user)
279 {       
280         static pstring user_name;
281         static pstring fullname;
282         static pstring home_dir;
283         static pstring dir_drive;
284         static pstring logon_script;
285         static pstring profile_path;
286         static pstring acct_desc;
287         static pstring workstations;
288         static pstring temp;
289         static struct smb_passwd pw_buf;
290
291         pdb_init_sam(user);
292
293         ldap_get_smb_passwd(ldap_struct, entry, &pw_buf);
294         
295         user->pass_last_set_time    = pw_buf.pass_last_set_time;
296
297         get_single_attribute(ldap_struct, entry, "logonTime", temp);
298         user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
299
300         get_single_attribute(ldap_struct, entry, "logoffTime", temp);
301         user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
302
303         get_single_attribute(ldap_struct, entry, "kickoffTime", temp);
304         user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
305
306         get_single_attribute(ldap_struct, entry, "pwdLastSet", temp);
307         user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
308
309         get_single_attribute(ldap_struct, entry, "pwdCanChange", temp);
310         user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
311
312         get_single_attribute(ldap_struct, entry, "pwdMustChange", temp);
313         user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
314
315         user->smb_name = pw_buf.smb_name;
316
317         DEBUG(2,("ldap_get_sam_passwd: user: %s\n", user_name));
318                 
319         get_single_attribute(ldap_struct, entry, "userFullName", fullname);
320         user->full_name = fullname;
321
322         get_single_attribute(ldap_struct, entry, "homeDirectory", home_dir);
323         user->home_dir = home_dir;
324
325         get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive);
326         user->dir_drive = dir_drive;
327
328         get_single_attribute(ldap_struct, entry, "scriptPath", logon_script);
329         user->logon_script = logon_script;
330
331         get_single_attribute(ldap_struct, entry, "profilePath", profile_path);
332         user->profile_path = profile_path;
333
334         get_single_attribute(ldap_struct, entry, "comment", acct_desc);
335         user->acct_desc = acct_desc;
336
337         get_single_attribute(ldap_struct, entry, "userWorkstations", workstations);
338         user->workstations = workstations;
339
340         user->unknown_str = NULL; /* don't know, yet! */
341         user->munged_dial = NULL; /* "munged" dial-back telephone number */
342
343         get_single_attribute(ldap_struct, entry, "rid", temp);
344         user->user_rid = atoi(temp);
345
346         get_single_attribute(ldap_struct, entry, "primaryGroupID", temp);
347         user->group_rid = atoi(temp);
348
349         /* the smb (unix) ids are not stored: they are created */
350         user->smb_userid = pw_buf.smb_userid;
351         user->smb_grpid = group_rid_to_uid(user->group_rid);
352
353         user->acct_ctrl = pw_buf.acct_ctrl;
354
355         user->unknown_3 = 0xffffff; /* don't know */
356         user->logon_divs = 168; /* hours per week */
357         user->hours_len = 21; /* 21 times 8 bits = 168 */
358         memset(user->hours, 0xff, user->hours_len); /* available at all hours */
359         user->unknown_5 = 0x00020000; /* don't know */
360         user->unknown_5 = 0x000004ec; /* don't know */
361
362         if (user->acct_ctrl & (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST) )
363         {
364                 DEBUG(0,("Inconsistency in the LDAP database\n"));
365         }
366
367         if (!(user->acct_ctrl & ACB_NORMAL))
368         {
369                 DEBUG(0,("User's acct_ctrl bits not set to ACT_NORMAL in LDAP database\n"));
370                 return;
371         }
372 }
373
374 /************************************************************************
375  Routine to manage the LDAPMod structure array
376  manage memory used by the array, by each struct, and values
377
378 ************************************************************************/
379 static void make_a_mod(LDAPMod ***modlist,int modop, char *attribute, char *value)
380 {
381         LDAPMod **mods;
382         int i;
383         int j;
384         
385         mods = *modlist;
386         
387         if (mods == NULL)
388         {
389                 mods = (LDAPMod **)malloc( sizeof(LDAPMod *) );
390                 if (mods == NULL)
391                 {
392                         DEBUG(0,("make_a_mod: out of memory!\n"));
393                         return;
394                 }
395                 mods[0] = NULL;
396         }
397         
398         for ( i = 0; mods[ i ] ! = NULL; ++i )
399         {
400                 if ( mods[ i ]->mod_op == modop && 
401                     !strcasecmp( mods[ i ]->mod_type, attribute ) )
402                 {
403                         break;
404                 }
405         }
406         
407         if (mods[i] == NULL)
408         {
409                 mods = (LDAPMod **)realloc( mods,  (i+2) * sizeof( LDAPMod * ) );       
410                 if (mods == NULL)
411                 {
412                         DEBUG(0,("make_a_mod: out of memory!\n"));
413                         return;
414                 }
415                 mods[i] = (LDAPMod *)malloc( sizeof( LDAPMod ) );
416                 if (mods[i] == NULL)
417                 {
418                         DEBUG(0,("make_a_mod: out of memory!\n"));
419                         return;
420                 }
421                 mods[i]->mod_op = modop;
422                 mods[i]->mod_values = NULL;
423                 mods[i]->mod_type = strdup( attribute );
424                 mods[i+1] = NULL;
425         }
426
427         if (value ! = NULL )
428         {
429                 j = 0;
430                 if ( mods[ i ]->mod_values ! = NULL )
431                 {
432                         for ( ; mods[ i ]->mod_values[ j ] ! = NULL; j++ );
433                 }
434                 mods[ i ]->mod_values = (char **)realloc(mods[ i ]->mod_values,
435                                                           (j+2) * sizeof( char * ));
436                 if ( mods[ i ]->mod_values == NULL)
437                 {
438                         DEBUG(0, "make_a_mod: Memory allocation failure!\n");
439                         return;
440                 }
441                 mods[ i ]->mod_values[ j ] = strdup(value);     
442                 mods[ i ]->mod_values[ j + 1 ] = NULL;          
443         }
444         *modlist = mods;
445 }
446
447 /************************************************************************
448  Add or modify an entry. Only the smb struct values
449
450 *************************************************************************/
451 static BOOL modadd_ldappwd_entry(struct smb_passwd *newpwd, int flag)
452 {
453         
454         /* assume the struct is correct and filled
455            that's the job of passdb.c to check */
456         int scope = LDAP_SCOPE_ONELEVEL;
457         int rc;
458         char *smb_name;
459         int trust = False;
460         int ldap_state;
461         pstring filter;
462         pstring dn;
463         pstring lmhash;
464         pstring nthash;
465         pstring rid;
466         pstring lst;
467         pstring temp;
468
469         LDAP *ldap_struct;
470         LDAPMessage *result;
471         LDAPMod **mods;
472         
473         smb_name = newpwd->smb_name;
474
475         if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
476         {
477                 return False;
478         }
479
480         if (!ldap_connect_system(ldap_struct)) /* connect as system account */
481         {
482                 ldap_unbind(ldap_struct);
483                 return False;
484         }
485         
486         if (smb_name[strlen(smb_name)-1] == '$' )
487         {
488                 smb_name[strlen(smb_name)-1] = '\0';
489                 trust = True;
490         }
491
492         slprintf(filter, sizeof(filter)-1,
493                  "(&(cn = %s)(|(objectclass = sambaTrust)(objectclass = sambaAccount)))",
494                  smb_name);
495         
496         rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &result);
497
498         switch (flag)
499         {
500                 case ADD_USER:
501                 {
502                         if (ldap_count_entries(ldap_struct, result) ! = 0)
503                         {
504                                 DEBUG(0,("User already in the base, with samba properties\n"));         
505                                 ldap_unbind(ldap_struct);
506                                 return False;
507                         }
508                         ldap_state = LDAP_MOD_ADD;
509                         break;
510                 }
511                 case MODIFY_USER:
512                 {
513                         if (ldap_count_entries(ldap_struct, result) ! = 1)
514                         {
515                                 DEBUG(0,("No user to modify !\n"));             
516                                 ldap_unbind(ldap_struct);
517                                 return False;
518                         }
519                         ldap_state = LDAP_MOD_REPLACE;
520                         break;
521                 }
522                 default:
523                 {
524                         DEBUG(0,("How did you come here? \n"));         
525                         ldap_unbind(ldap_struct);
526                         return False;
527                         break;
528                 }
529         }
530         slprintf(dn, sizeof(dn)-1, "cn = %s, %s",smb_name, lp_ldap_suffix() );
531
532         if (newpwd->smb_passwd ! = NULL)
533         {
534                 int i;
535                 for( i = 0; i < 16; i++)
536                 {
537                         slprintf(&temp[2*i], sizeof(temp) - 1, "%02X", newpwd->smb_passwd[i]);
538                 }
539         
540         }
541         else
542         {
543                 if (newpwd->acct_ctrl & ACB_PWNOTREQ)
544                 {
545                         slprintf(temp, sizeof(temp) - 1, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
546                 }
547                 else
548                 {
549                         slprintf(temp, sizeof(temp) - 1, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
550                 }
551         }
552         slprintf(lmhash, sizeof(lmhash)-1, "%s", temp);
553
554         if (newpwd->smb_nt_passwd ! = NULL)
555         {
556                 int i;
557                 for( i = 0; i < 16; i++)
558                 {
559                         slprintf(&temp[2*i], sizeof(temp) - 1, "%02X", newpwd->smb_nt_passwd[i]);
560                 }
561         
562         }
563         else
564         {
565                 if (newpwd->acct_ctrl & ACB_PWNOTREQ)
566                 {
567                         slprintf(temp, sizeof(temp) - 1, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
568                 }
569                 else
570                 {
571                         slprintf(temp, sizeof(temp) - 1, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
572                 }
573         }
574         slprintf(nthash, sizeof(nthash)-1, "%s", temp);
575
576         slprintf(rid, sizeof(rid)-1, "%d", uid_to_user_rid(newpwd->smb_userid) );
577         slprintf(lst, sizeof(lst)-1, "%08X", newpwd->pass_last_set_time);
578         
579         mods = NULL; 
580
581         if (trust)
582         {
583                 make_a_mod(&mods, ldap_state, "objectclass", "sambaTrust");
584                 make_a_mod(&mods, ldap_state, "netbiosTrustName", smb_name);
585                 make_a_mod(&mods, ldap_state, "trustPassword", nthash);
586         }
587         else
588         {
589                 make_a_mod(&mods, ldap_state, "objectclass", "sambaAccount");
590                 make_a_mod(&mods, ldap_state, "dBCSPwd", lmhash);
591                 make_a_mod(&mods, ldap_state, "uid", smb_name);
592                 make_a_mod(&mods, ldap_state, "unicodePwd", nthash);
593         }
594         
595         make_a_mod(&mods, ldap_state, "cn", smb_name);
596         
597         make_a_mod(&mods, ldap_state, "rid", rid);
598         make_a_mod(&mods, ldap_state, "pwdLastSet", lst);
599         make_a_mod(&mods, ldap_state, "userAccountControl", pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
600         
601         switch(flag)
602         {
603                 case ADD_USER:
604                 {
605                         ldap_add_s(ldap_struct, dn, mods);
606                         DEBUG(2,("modadd_ldappwd_entry: added: cn = %s in the LDAP database\n",smb_name));
607                         break;
608                 }
609                 case MODIFY_USER:
610                 {
611                         ldap_modify_s(ldap_struct, dn, mods);
612                         DEBUG(2,("modadd_ldappwd_entry: changed: cn = %s in the LDAP database_n",smb_name));
613                         break;
614                 }
615                 default:
616                 {
617                         DEBUG(2,("modadd_ldappwd_entry: How did you come here? \n"));           
618                         ldap_unbind(ldap_struct);
619                         return False;
620                         break;
621                 }
622         }
623         
624         ldap_mods_free(mods, 1);
625         
626         ldap_unbind(ldap_struct);
627         
628         return True;
629 }
630
631 /************************************************************************
632  Add or modify an entry. everything except the smb struct
633
634 *************************************************************************/
635 static BOOL modadd_ldap21pwd_entry(struct sam_passwd *newpwd, int flag)
636 {
637         
638         /* assume the struct is correct and filled
639            that's the job of passdb.c to check */
640         int scope = LDAP_SCOPE_ONELEVEL;
641         int rc;
642         char *smb_name;
643         int trust = False;
644         int ldap_state;
645         pstring filter;
646         pstring dn;
647         pstring lmhash;
648         pstring nthash;
649         pstring rid;
650         pstring lst;
651         pstring temp;
652
653         LDAP *ldap_struct;
654         LDAPMessage *result;
655         LDAPMod **mods;
656         
657         smb_name = newpwd->smb_name;
658
659         if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
660         {
661                 return False;
662         }
663
664         if (!ldap_connect_system(ldap_struct)) /* connect as system account */
665         {
666                 ldap_unbind(ldap_struct);
667                 return False;
668         }
669         
670         if (smb_name[strlen(smb_name)-1] == '$' )
671         {
672                 smb_name[strlen(smb_name)-1] = '\0';
673                 trust = True;
674         }
675
676         slprintf(filter, sizeof(filter)-1,
677                  "(&(cn = %s)(|(objectclass = sambaTrust)(objectclass = sambaAccount)))",
678                  smb_name);
679         
680         rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &result);
681
682         switch (flag)
683         {
684                 case ADD_USER:
685                 {
686                         if (ldap_count_entries(ldap_struct, result) ! = 1)
687                         {
688                                 DEBUG(2,("User already in the base, with samba properties\n"));         
689                                 ldap_unbind(ldap_struct);
690                                 return False;
691                         }
692                         ldap_state = LDAP_MOD_ADD;
693                         break;
694                 }
695
696                 case MODIFY_USER:
697                 {
698                         if (ldap_count_entries(ldap_struct, result) ! = 1)
699                         {
700                                 DEBUG(2,("No user to modify !\n"));             
701                                 ldap_unbind(ldap_struct);
702                                 return False;
703                         }
704                         ldap_state = LDAP_MOD_REPLACE;
705                         break;
706                 }
707
708                 default:
709                 {
710                         DEBUG(2,("How did you come here? \n"));         
711                         ldap_unbind(ldap_struct);
712                         return False;
713                         break;
714                 }
715         }
716         slprintf(dn, sizeof(dn)-1, "cn = %s, %s",smb_name, lp_ldap_suffix() );
717         
718         mods = NULL; 
719
720         if (trust)
721         {
722         }
723         else
724         {
725         }
726         
727         make_a_mod(&mods, ldap_state, "cn", smb_name);
728         
729         make_a_mod(&mods, ldap_state, "rid", rid);
730         make_a_mod(&mods, ldap_state, "pwdLastSet", lst);
731         make_a_mod(&mods, ldap_state, "userAccountControl", pdb_encode_acct_ctrl(newpwd->acct_ctrl,NEW_PW_FORMAT_SPACE_PADDED_LEN));
732         
733         ldap_modify_s(ldap_struct, dn, mods);
734         
735         ldap_mods_free(mods, 1);
736         
737         ldap_unbind(ldap_struct);
738         
739         return True;
740 }
741
742 /************************************************************************
743  Routine to add an entry to the ldap passwd file.
744
745  do not call this function directly.  use passdb.c instead.
746
747 *************************************************************************/
748 static BOOL add_ldappwd_entry(struct smb_passwd *newpwd)
749 {
750         return (modadd_ldappwd_entry(newpwd, ADD_USER) );
751 }
752
753 /************************************************************************
754  Routine to search the ldap passwd file for an entry matching the username.
755  and then modify its password entry. We can't use the startldappwent()/
756  getldappwent()/endldappwent() interfaces here as we depend on looking
757  in the actual file to decide how much room we have to write data.
758  override = False, normal
759  override = True, override XXXXXXXX'd out password or NO PASS
760
761  do not call this function directly.  use passdb.c instead.
762
763 ************************************************************************/
764 static BOOL mod_ldappwd_entry(struct smb_passwd *pwd, BOOL override)
765 {
766         return (modadd_ldappwd_entry(pwd, MODIFY_USER) );
767 }
768
769 /************************************************************************
770  Routine to add an entry to the ldap passwd file.
771
772  do not call this function directly.  use passdb.c instead.
773
774 *************************************************************************/
775 static BOOL add_ldap21pwd_entry(struct sam_passwd *newpwd)
776 {       
777         return( modadd_ldappwd_entry(newpwd, ADD_USER)?
778         modadd_ldap21pwd_entry(newpwd, ADD_USER):False);
779 }
780
781 /************************************************************************
782  Routine to search the ldap passwd file for an entry matching the username.
783  and then modify its password entry. We can't use the startldappwent()/
784  getldappwent()/endldappwent() interfaces here as we depend on looking
785  in the actual file to decide how much room we have to write data.
786  override = False, normal
787  override = True, override XXXXXXXX'd out password or NO PASS
788
789  do not call this function directly.  use passdb.c instead.
790
791 ************************************************************************/
792 static BOOL mod_ldap21pwd_entry(struct sam_passwd *pwd, BOOL override)
793 {
794         return( modadd_ldappwd_entry(pwd, MODIFY_USER)?
795         modadd_ldap21pwd_entry(pwd, MODIFY_USER):False);
796 }
797
798 struct ldap_enum_info
799 {
800         LDAP *ldap_struct;
801         LDAPMessage *result;
802         LDAPMessage *entry;
803 };
804
805 static struct ldap_enum_info ldap_ent;
806
807 /***************************************************************
808  Start to enumerate the ldap passwd list. Returns a void pointer
809  to ensure no modification outside this module.
810
811  do not call this function directly.  use passdb.c instead.
812
813  ****************************************************************/
814 static void *startldappwent(BOOL update)
815 {
816         int scope = LDAP_SCOPE_ONELEVEL;
817         int rc;
818
819         pstring filter;
820
821         if (!ldap_open_connection(&ldap_ent.ldap_struct)) /* open a connection to the server */
822         {
823                 return NULL;
824         }
825
826         if (!ldap_connect_system(ldap_ent.ldap_struct)) /* connect as system account */
827         {
828                 return NULL;
829         }
830
831         /* when the class is known the search is much faster */
832         switch (0)
833         {
834                 case 1:
835                 {
836                         pstrcpy(filter, "objectclass = sambaAccount");
837                         break;
838                 }
839                 case 2:
840                 {
841                         pstrcpy(filter, "objectclass = sambaTrust");
842                         break;
843                 }
844                 default:
845                 {
846                         pstrcpy(filter, "(|(objectclass = sambaTrust)(objectclass = sambaAccount))");
847                         break;
848                 }
849         }
850
851         rc = ldap_search_s(ldap_ent.ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &ldap_ent.result);
852
853         DEBUG(2,("%d entries in the base!\n", ldap_count_entries(ldap_ent.ldap_struct, ldap_ent.result) ));
854
855         ldap_ent.entry = ldap_first_entry(ldap_ent.ldap_struct, ldap_ent.result);
856
857         return &ldap_ent;
858 }
859
860 /*************************************************************************
861  Routine to return the next entry in the ldap passwd list.
862
863  do not call this function directly.  use passdb.c instead.
864
865  *************************************************************************/
866 static struct smb_passwd *getldappwent(void *vp)
867 {
868         static struct smb_passwd user;
869         struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp;
870
871         ldap_vp->entry = ldap_next_entry(ldap_vp->ldap_struct, ldap_vp->entry);
872
873         if (ldap_vp->entry ! = NULL)
874         {
875                 ldap_get_smb_passwd(ldap_vp->ldap_struct, ldap_vp->entry, &user);
876                 return &user;
877         }
878         return NULL;
879 }
880
881 /*************************************************************************
882  Routine to return the next entry in the ldap passwd list.
883
884  do not call this function directly.  use passdb.c instead.
885
886  *************************************************************************/
887 static struct sam_passwd *getldap21pwent(void *vp)
888 {
889         static struct sam_passwd user;
890         struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp;
891
892         ldap_vp->entry = ldap_next_entry(ldap_vp->ldap_struct, ldap_vp->entry);
893
894         if (ldap_vp->entry ! = NULL)
895         {
896                 ldap_get_sam_passwd(ldap_vp->ldap_struct, ldap_vp->entry, &user);
897                 return &user;
898         }
899         return NULL;
900 }
901
902 /***************************************************************
903  End enumeration of the ldap passwd list.
904
905  do not call this function directly.  use passdb.c instead.
906
907 ****************************************************************/
908 static void endldappwent(void *vp)
909 {
910         struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp;
911         ldap_msgfree(ldap_vp->result);
912         ldap_unbind(ldap_vp->ldap_struct);
913 }
914
915 /*************************************************************************
916  Return the current position in the ldap passwd list as an SMB_BIG_UINT.
917  This must be treated as an opaque token.
918
919  do not call this function directly.  use passdb.c instead.
920
921 *************************************************************************/
922 static SMB_BIG_UINT getldappwpos(void *vp)
923 {
924         return (SMB_BIG_UINT)0;
925 }
926
927 /*************************************************************************
928  Set the current position in the ldap passwd list from SMB_BIG_UINT.
929  This must be treated as an opaque token.
930
931  do not call this function directly.  use passdb.c instead.
932
933 *************************************************************************/
934 static BOOL setldappwpos(void *vp, SMB_BIG_UINT tok)
935 {
936         return False;
937 }
938
939 /*
940  * Ldap derived functions.
941  */
942
943 static struct smb_passwd *getldappwnam(char *name)
944 {
945   return pdb_sam_to_smb(iterate_getsam21pwnam(name));
946 }
947
948 static struct smb_passwd *getldappwuid(uid_t smb_userid)
949 {
950   return pdb_sam_to_smb(iterate_getsam21pwuid(smb_userid));
951 }
952
953 static struct smb_passwd *getldappwrid(uint32 user_rid)
954 {
955   return pdb_sam_to_smb(iterate_getsam21pwuid(pdb_user_rid_to_uid(user_rid)));
956 }
957
958 static struct smb_passwd *getldappwent(void *vp)
959 {
960   return pdb_sam_to_smb(getldap21pwent(vp));
961 }
962
963 static BOOL add_ldappwd_entry(struct smb_passwd *newpwd)
964 {
965   return add_ldap21pwd_entry(pdb_smb_to_sam(newpwd));
966 }
967
968 static BOOL mod_ldappwd_entry(struct smb_passwd* pwd, BOOL override)
969 {
970   return mod_ldap21pwd_entry(pdb_smb_to_sam(pwd), override);
971 }
972
973 static BOOL del_ldappwd_entry(const char *name)
974 {
975   return False; /* Dummy... */
976 }
977
978 static struct sam_disp_info *getldapdispnam(char *name)
979 {
980         return pdb_sam_to_dispinfo(getldap21pwnam(name));
981 }
982
983 static struct sam_disp_info *getldapdisprid(uint32 rid)
984 {
985         return pdb_sam_to_dispinfo(getldap21pwrid(rid));
986 }
987
988 static struct sam_disp_info *getldapdispent(void *vp)
989 {
990         return pdb_sam_to_dispinfo(getldap21pwent(vp));
991 }
992
993 static struct sam_passwd *getldap21pwuid(uid_t uid)
994 {
995         return pdb_smb_to_sam(iterate_getsam21pwuid(pdb_uid_to_user_rid(uid)));
996 }
997
998 static struct passdb_ops ldap_ops =
999 {
1000         startldappwent,
1001         endldappwent,
1002         getldappwpos,
1003         setldappwpos,
1004         getldappwnam,
1005         getldappwuid,
1006         getldappwrid,
1007         getldappwent,
1008         add_ldappwd_entry,
1009         mod_ldappwd_entry,
1010         del_ldappwd_entry,
1011         getldap21pwent,
1012         iterate_getsam21pwnam,       /* From passdb.c */
1013         iterate_getsam21pwuid,       /* From passdb.c */
1014         iterate_getsam21pwrid,       /* From passdb.c */
1015         add_ldap21pwd_entry,
1016         mod_ldap21pwd_entry,
1017         getldapdispnam,
1018         getldapdisprid,
1019         getldapdispent
1020 };
1021
1022 struct passdb_ops *ldap_initialize_password_db(void)
1023 {
1024   return &ldap_ops;
1025 }
1026
1027 #else
1028  void dummy_function(void);
1029  void dummy_function(void) { } /* stop some compilers complaining */
1030 #endif