8a2befcaa8644faf49398ecd64729c10d245eb22
[metze/samba/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 = 0x00000000; /* don't know */
360         user->unknown_6 = 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, **tmods;
382         int i;
383         int j;
384         
385         mods = *modlist;
386         
387         if (mods == NULL)
388         {
389                 tmods = (LDAPMod **)malloc( sizeof(LDAPMod *) );
390                 if (tmods == NULL)
391                 {
392                         DEBUG(0,("make_a_mod: out of memory!\n"));
393                         return;
394                 }
395                 mods = tmods;
396                 mods[0] = NULL;
397         }
398         
399         for ( i = 0; mods[ i ] ! = NULL; ++i )
400         {
401                 if ( mods[ i ]->mod_op == modop && 
402                     !strcasecmp( mods[ i ]->mod_type, attribute ) )
403                 {
404                         break;
405                 }
406         }
407         
408         if (mods[i] == NULL)
409         {
410                 tmods = (LDAPMod **)Realloc( mods,  (i+2) * sizeof( LDAPMod * ) );      
411                 if (tmods == NULL)
412                 {
413                         DEBUG(0,("make_a_mod: out of memory!\n"));
414                         return;
415                 }
416                 mods = tmods;
417                 mods[i] = (LDAPMod *)malloc( sizeof( LDAPMod ) );
418                 if (mods[i] == NULL)
419                 {
420                         DEBUG(0,("make_a_mod: out of memory!\n"));
421                         return;
422                 }
423                 mods[i]->mod_op = modop;
424                 mods[i]->mod_values = NULL;
425                 mods[i]->mod_type = strdup( attribute );
426                 mods[i+1] = NULL;
427         }
428
429         if (value ! = NULL )
430         {
431                 char **tmval;
432                 
433                 j = 0;
434                 if ( mods[ i ]->mod_values ! = NULL )
435                 {
436                         for ( ; mods[ i ]->mod_values[ j ] ! = NULL; j++ );
437                 }
438                 tmval = (char **)Realloc(mods[ i ]->mod_values,
439                                                           (j+2) * sizeof( char * ));
440                 if ( tmval == NULL)
441                 {
442                         DEBUG(0, "make_a_mod: Memory allocation failure!\n");
443                         return;
444                 }
445                 mods[ i ]->mod_values = tmval;
446                 mods[ i ]->mod_values[ j ] = strdup(value);     
447                 mods[ i ]->mod_values[ j + 1 ] = NULL;          
448         }
449         *modlist = mods;
450 }
451
452 /************************************************************************
453  Add or modify an entry. Only the smb struct values
454
455 *************************************************************************/
456 static BOOL modadd_ldappwd_entry(struct smb_passwd *newpwd, int flag)
457 {
458         
459         /* assume the struct is correct and filled
460            that's the job of passdb.c to check */
461         int scope = LDAP_SCOPE_ONELEVEL;
462         int rc;
463         char *smb_name;
464         int trust = False;
465         int ldap_state;
466         pstring filter;
467         pstring dn;
468         pstring lmhash;
469         pstring nthash;
470         pstring rid;
471         pstring lst;
472         pstring temp;
473
474         LDAP *ldap_struct;
475         LDAPMessage *result;
476         LDAPMod **mods;
477         
478         smb_name = newpwd->smb_name;
479
480         if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
481         {
482                 return False;
483         }
484
485         if (!ldap_connect_system(ldap_struct)) /* connect as system account */
486         {
487                 ldap_unbind(ldap_struct);
488                 return False;
489         }
490         
491         if (smb_name[strlen(smb_name)-1] == '$' )
492         {
493                 smb_name[strlen(smb_name)-1] = '\0';
494                 trust = True;
495         }
496
497         slprintf(filter, sizeof(filter)-1,
498                  "(&(cn = %s)(|(objectclass = sambaTrust)(objectclass = sambaAccount)))",
499                  smb_name);
500         
501         rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &result);
502
503         switch (flag)
504         {
505                 case ADD_USER:
506                 {
507                         if (ldap_count_entries(ldap_struct, result) ! = 0)
508                         {
509                                 DEBUG(0,("User already in the base, with samba properties\n"));         
510                                 ldap_unbind(ldap_struct);
511                                 return False;
512                         }
513                         ldap_state = LDAP_MOD_ADD;
514                         break;
515                 }
516                 case MODIFY_USER:
517                 {
518                         if (ldap_count_entries(ldap_struct, result) ! = 1)
519                         {
520                                 DEBUG(0,("No user to modify !\n"));             
521                                 ldap_unbind(ldap_struct);
522                                 return False;
523                         }
524                         ldap_state = LDAP_MOD_REPLACE;
525                         break;
526                 }
527                 default:
528                 {
529                         DEBUG(0,("How did you come here? \n"));         
530                         ldap_unbind(ldap_struct);
531                         return False;
532                         break;
533                 }
534         }
535         slprintf(dn, sizeof(dn)-1, "cn = %s, %s",smb_name, lp_ldap_suffix() );
536
537         if (newpwd->smb_passwd ! = NULL)
538         {
539                 int i;
540                 for( i = 0; i < 16; i++)
541                 {
542                         slprintf(&temp[2*i], sizeof(temp) - 1, "%02X", newpwd->smb_passwd[i]);
543                 }
544         
545         }
546         else
547         {
548                 if (newpwd->acct_ctrl & ACB_PWNOTREQ)
549                 {
550                         slprintf(temp, sizeof(temp) - 1, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
551                 }
552                 else
553                 {
554                         slprintf(temp, sizeof(temp) - 1, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
555                 }
556         }
557         slprintf(lmhash, sizeof(lmhash)-1, "%s", temp);
558
559         if (newpwd->smb_nt_passwd ! = NULL)
560         {
561                 int i;
562                 for( i = 0; i < 16; i++)
563                 {
564                         slprintf(&temp[2*i], sizeof(temp) - 1, "%02X", newpwd->smb_nt_passwd[i]);
565                 }
566         
567         }
568         else
569         {
570                 if (newpwd->acct_ctrl & ACB_PWNOTREQ)
571                 {
572                         slprintf(temp, sizeof(temp) - 1, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
573                 }
574                 else
575                 {
576                         slprintf(temp, sizeof(temp) - 1, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
577                 }
578         }
579         slprintf(nthash, sizeof(nthash)-1, "%s", temp);
580
581         slprintf(rid, sizeof(rid)-1, "%d", uid_to_user_rid(newpwd->smb_userid) );
582         slprintf(lst, sizeof(lst)-1, "%08X", newpwd->pass_last_set_time);
583         
584         mods = NULL; 
585
586         if (trust)
587         {
588                 make_a_mod(&mods, ldap_state, "objectclass", "sambaTrust");
589                 make_a_mod(&mods, ldap_state, "netbiosTrustName", smb_name);
590                 make_a_mod(&mods, ldap_state, "trustPassword", nthash);
591         }
592         else
593         {
594                 make_a_mod(&mods, ldap_state, "objectclass", "sambaAccount");
595                 make_a_mod(&mods, ldap_state, "dBCSPwd", lmhash);
596                 make_a_mod(&mods, ldap_state, "uid", smb_name);
597                 make_a_mod(&mods, ldap_state, "unicodePwd", nthash);
598         }
599         
600         make_a_mod(&mods, ldap_state, "cn", smb_name);
601         
602         make_a_mod(&mods, ldap_state, "rid", rid);
603         make_a_mod(&mods, ldap_state, "pwdLastSet", lst);
604         make_a_mod(&mods, ldap_state, "userAccountControl", 
605                    smbpasswd_encode_acb_info(newpwd->acct_ctrl));
606         
607         switch(flag)
608         {
609                 case ADD_USER:
610                 {
611                         ldap_add_s(ldap_struct, dn, mods);
612                         DEBUG(2,("modadd_ldappwd_entry: added: cn = %s in the LDAP database\n",smb_name));
613                         break;
614                 }
615                 case MODIFY_USER:
616                 {
617                         ldap_modify_s(ldap_struct, dn, mods);
618                         DEBUG(2,("modadd_ldappwd_entry: changed: cn = %s in the LDAP database_n",smb_name));
619                         break;
620                 }
621                 default:
622                 {
623                         DEBUG(2,("modadd_ldappwd_entry: How did you come here? \n"));           
624                         ldap_unbind(ldap_struct);
625                         return False;
626                         break;
627                 }
628         }
629         
630         ldap_mods_free(mods, 1);
631         
632         ldap_unbind(ldap_struct);
633         
634         return True;
635 }
636
637 /************************************************************************
638  Add or modify an entry. everything except the smb struct
639
640 *************************************************************************/
641 static BOOL modadd_ldap21pwd_entry(struct sam_passwd *newpwd, int flag)
642 {
643         
644         /* assume the struct is correct and filled
645            that's the job of passdb.c to check */
646         int scope = LDAP_SCOPE_ONELEVEL;
647         int rc;
648         char *smb_name;
649         int trust = False;
650         int ldap_state;
651         pstring filter;
652         pstring dn;
653         pstring lmhash;
654         pstring nthash;
655         pstring rid;
656         pstring lst;
657         pstring temp;
658
659         LDAP *ldap_struct;
660         LDAPMessage *result;
661         LDAPMod **mods;
662         
663         smb_name = newpwd->smb_name;
664
665         if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
666         {
667                 return False;
668         }
669
670         if (!ldap_connect_system(ldap_struct)) /* connect as system account */
671         {
672                 ldap_unbind(ldap_struct);
673                 return False;
674         }
675         
676         if (smb_name[strlen(smb_name)-1] == '$' )
677         {
678                 smb_name[strlen(smb_name)-1] = '\0';
679                 trust = True;
680         }
681
682         slprintf(filter, sizeof(filter)-1,
683                  "(&(cn = %s)(|(objectclass = sambaTrust)(objectclass = sambaAccount)))",
684                  smb_name);
685         
686         rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &result);
687
688         switch (flag)
689         {
690                 case ADD_USER:
691                 {
692                         if (ldap_count_entries(ldap_struct, result) ! = 1)
693                         {
694                                 DEBUG(2,("User already in the base, with samba properties\n"));         
695                                 ldap_unbind(ldap_struct);
696                                 return False;
697                         }
698                         ldap_state = LDAP_MOD_ADD;
699                         break;
700                 }
701
702                 case MODIFY_USER:
703                 {
704                         if (ldap_count_entries(ldap_struct, result) ! = 1)
705                         {
706                                 DEBUG(2,("No user to modify !\n"));             
707                                 ldap_unbind(ldap_struct);
708                                 return False;
709                         }
710                         ldap_state = LDAP_MOD_REPLACE;
711                         break;
712                 }
713
714                 default:
715                 {
716                         DEBUG(2,("How did you come here? \n"));         
717                         ldap_unbind(ldap_struct);
718                         return False;
719                         break;
720                 }
721         }
722         slprintf(dn, sizeof(dn)-1, "cn = %s, %s",smb_name, lp_ldap_suffix() );
723         
724         mods = NULL; 
725
726         if (trust)
727         {
728         }
729         else
730         {
731         }
732         
733         make_a_mod(&mods, ldap_state, "cn", smb_name);
734         
735         make_a_mod(&mods, ldap_state, "rid", rid);
736         make_a_mod(&mods, ldap_state, "pwdLastSet", lst);
737         make_a_mod(&mods, ldap_state, "userAccountControl", 
738                    smbpasswd_encode_acct_ctrl(newpwd->acct_ctrl));
739         
740         ldap_modify_s(ldap_struct, dn, mods);
741         
742         ldap_mods_free(mods, 1);
743         
744         ldap_unbind(ldap_struct);
745         
746         return True;
747 }
748
749 /************************************************************************
750  Routine to add an entry to the ldap passwd file.
751
752  do not call this function directly.  use passdb.c instead.
753
754 *************************************************************************/
755 static BOOL add_ldappwd_entry(struct smb_passwd *newpwd)
756 {
757         return (modadd_ldappwd_entry(newpwd, ADD_USER) );
758 }
759
760 /************************************************************************
761  Routine to search the ldap passwd file for an entry matching the username.
762  and then modify its password entry. We can't use the startldappwent()/
763  getldappwent()/endldappwent() interfaces here as we depend on looking
764  in the actual file to decide how much room we have to write data.
765  override = False, normal
766  override = True, override XXXXXXXX'd out password or NO PASS
767
768  do not call this function directly.  use passdb.c instead.
769
770 ************************************************************************/
771 static BOOL mod_ldappwd_entry(struct smb_passwd *pwd, BOOL override)
772 {
773         return (modadd_ldappwd_entry(pwd, MODIFY_USER) );
774 }
775
776 /************************************************************************
777  Routine to add an entry to the ldap passwd file.
778
779  do not call this function directly.  use passdb.c instead.
780
781 *************************************************************************/
782 static BOOL add_ldap21pwd_entry(struct sam_passwd *newpwd)
783 {       
784         return( modadd_ldappwd_entry(newpwd, ADD_USER)?
785         modadd_ldap21pwd_entry(newpwd, ADD_USER):False);
786 }
787
788 /************************************************************************
789  Routine to search the ldap passwd file for an entry matching the username.
790  and then modify its password entry. We can't use the startldappwent()/
791  getldappwent()/endldappwent() interfaces here as we depend on looking
792  in the actual file to decide how much room we have to write data.
793  override = False, normal
794  override = True, override XXXXXXXX'd out password or NO PASS
795
796  do not call this function directly.  use passdb.c instead.
797
798 ************************************************************************/
799 static BOOL mod_ldap21pwd_entry(struct sam_passwd *pwd, BOOL override)
800 {
801         return( modadd_ldappwd_entry(pwd, MODIFY_USER)?
802         modadd_ldap21pwd_entry(pwd, MODIFY_USER):False);
803 }
804
805 struct ldap_enum_info
806 {
807         LDAP *ldap_struct;
808         LDAPMessage *result;
809         LDAPMessage *entry;
810 };
811
812 static struct ldap_enum_info ldap_ent;
813
814 /***************************************************************
815  Start to enumerate the ldap passwd list. Returns a void pointer
816  to ensure no modification outside this module.
817
818  do not call this function directly.  use passdb.c instead.
819
820  ****************************************************************/
821 static void *startldappwent(BOOL update)
822 {
823         int scope = LDAP_SCOPE_ONELEVEL;
824         int rc;
825
826         pstring filter;
827
828         if (!ldap_open_connection(&ldap_ent.ldap_struct)) /* open a connection to the server */
829         {
830                 return NULL;
831         }
832
833         if (!ldap_connect_system(ldap_ent.ldap_struct)) /* connect as system account */
834         {
835                 return NULL;
836         }
837
838         /* when the class is known the search is much faster */
839         switch (0)
840         {
841                 case 1:
842                 {
843                         pstrcpy(filter, "objectclass = sambaAccount");
844                         break;
845                 }
846                 case 2:
847                 {
848                         pstrcpy(filter, "objectclass = sambaTrust");
849                         break;
850                 }
851                 default:
852                 {
853                         pstrcpy(filter, "(|(objectclass = sambaTrust)(objectclass = sambaAccount))");
854                         break;
855                 }
856         }
857
858         rc = ldap_search_s(ldap_ent.ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &ldap_ent.result);
859
860         DEBUG(2,("%d entries in the base!\n", ldap_count_entries(ldap_ent.ldap_struct, ldap_ent.result) ));
861
862         ldap_ent.entry = ldap_first_entry(ldap_ent.ldap_struct, ldap_ent.result);
863
864         return &ldap_ent;
865 }
866
867 /*************************************************************************
868  Routine to return the next entry in the ldap passwd list.
869
870  do not call this function directly.  use passdb.c instead.
871
872  *************************************************************************/
873 static struct smb_passwd *getldappwent(void *vp)
874 {
875         static struct smb_passwd user;
876         struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp;
877
878         ldap_vp->entry = ldap_next_entry(ldap_vp->ldap_struct, ldap_vp->entry);
879
880         if (ldap_vp->entry ! = NULL)
881         {
882                 ldap_get_smb_passwd(ldap_vp->ldap_struct, ldap_vp->entry, &user);
883                 return &user;
884         }
885         return NULL;
886 }
887
888 /*************************************************************************
889  Routine to return the next entry in the ldap passwd list.
890
891  do not call this function directly.  use passdb.c instead.
892
893  *************************************************************************/
894 static struct sam_passwd *getldap21pwent(void *vp)
895 {
896         static struct sam_passwd user;
897         struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp;
898
899         ldap_vp->entry = ldap_next_entry(ldap_vp->ldap_struct, ldap_vp->entry);
900
901         if (ldap_vp->entry ! = NULL)
902         {
903                 ldap_get_sam_passwd(ldap_vp->ldap_struct, ldap_vp->entry, &user);
904                 return &user;
905         }
906         return NULL;
907 }
908
909 /***************************************************************
910  End enumeration of the ldap passwd list.
911
912  do not call this function directly.  use passdb.c instead.
913
914 ****************************************************************/
915 static void endldappwent(void *vp)
916 {
917         struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp;
918         ldap_msgfree(ldap_vp->result);
919         ldap_unbind(ldap_vp->ldap_struct);
920 }
921
922 /*************************************************************************
923  Return the current position in the ldap passwd list as an SMB_BIG_UINT.
924  This must be treated as an opaque token.
925
926  do not call this function directly.  use passdb.c instead.
927
928 *************************************************************************/
929 static SMB_BIG_UINT getldappwpos(void *vp)
930 {
931         return (SMB_BIG_UINT)0;
932 }
933
934 /*************************************************************************
935  Set the current position in the ldap passwd list from SMB_BIG_UINT.
936  This must be treated as an opaque token.
937
938  do not call this function directly.  use passdb.c instead.
939
940 *************************************************************************/
941 static BOOL setldappwpos(void *vp, SMB_BIG_UINT tok)
942 {
943         return False;
944 }
945
946 /*
947  * Ldap derived functions.
948  */
949
950 static struct smb_passwd *getldappwnam(char *name)
951 {
952   return pdb_sam_to_smb(iterate_getsam21pwnam(name));
953 }
954
955 static struct smb_passwd *getldappwuid(uid_t smb_userid)
956 {
957   return pdb_sam_to_smb(iterate_getsam21pwuid(smb_userid));
958 }
959
960 static struct smb_passwd *getldappwrid(uint32 user_rid)
961 {
962   return pdb_sam_to_smb(iterate_getsam21pwuid(pdb_user_rid_to_uid(user_rid)));
963 }
964
965 static struct smb_passwd *getldappwent(void *vp)
966 {
967   return pdb_sam_to_smb(getldap21pwent(vp));
968 }
969
970 static BOOL add_ldappwd_entry(struct smb_passwd *newpwd)
971 {
972   return add_ldap21pwd_entry(pdb_smb_to_sam(newpwd));
973 }
974
975 static BOOL mod_ldappwd_entry(struct smb_passwd* pwd, BOOL override)
976 {
977   return mod_ldap21pwd_entry(pdb_smb_to_sam(pwd), override);
978 }
979
980 static BOOL del_ldappwd_entry(const char *name)
981 {
982   return False; /* Dummy... */
983 }
984
985 static struct sam_disp_info *getldapdispnam(char *name)
986 {
987         return pdb_sam_to_dispinfo(getldap21pwnam(name));
988 }
989
990 static struct sam_disp_info *getldapdisprid(uint32 rid)
991 {
992         return pdb_sam_to_dispinfo(getldap21pwrid(rid));
993 }
994
995 static struct sam_disp_info *getldapdispent(void *vp)
996 {
997         return pdb_sam_to_dispinfo(getldap21pwent(vp));
998 }
999
1000 static struct sam_passwd *getldap21pwuid(uid_t uid)
1001 {
1002         return pdb_smb_to_sam(iterate_getsam21pwuid(pdb_uid_to_user_rid(uid)));
1003 }
1004
1005 static struct passdb_ops ldap_ops =
1006 {
1007         startldappwent,
1008         endldappwent,
1009         getldappwpos,
1010         setldappwpos,
1011         getldappwnam,
1012         getldappwuid,
1013         getldappwrid,
1014         getldappwent,
1015         add_ldappwd_entry,
1016         mod_ldappwd_entry,
1017         del_ldappwd_entry,
1018         getldap21pwent,
1019         iterate_getsam21pwnam,       /* From passdb.c */
1020         iterate_getsam21pwuid,       /* From passdb.c */
1021         iterate_getsam21pwrid,       /* From passdb.c */
1022         add_ldap21pwd_entry,
1023         mod_ldap21pwd_entry,
1024         getldapdispnam,
1025         getldapdisprid,
1026         getldapdispent
1027 };
1028
1029 struct passdb_ops *ldap_initialize_password_db(void)
1030 {
1031   return &ldap_ops;
1032 }
1033
1034 #else
1035  void dummy_function(void);
1036  void dummy_function(void) { } /* stop some compilers complaining */
1037 #endif