f4ed014efe06c722053e6eec1618afb753fad914
[kai/samba.git] / source3 / passdb / pdb_ldap.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.9.
4    LDAP protocol helper functions for SAMBA
5    Copyright (C) Shahms King 2001
6    Copyright (C) Jean François Micouleau 1998
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21    
22 */
23
24 #include "includes.h"
25
26 #ifdef WITH_LDAP_SAM
27 /* TODO:
28 *  persistent connections: if using NSS LDAP, many connections are made
29 *      however, using only one within Samba would be nice
30 *  
31 *  Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
32 *
33 *  Other LDAP based login attributes: accountExpires, etc.
34 *  (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
35 *  structures don't have fields for some of these attributes)
36 *
37 *  SSL is done, but can't get the certificate based authentication to work
38 *  against on my test platform (Linux 2.4, OpenLDAP 2.x)
39 */
40
41 /* NOTE: this will NOT work against an Active Directory server
42 *  due to the fact that the two password fields cannot be retrieved
43 *  from a server; recommend using security = domain in this situation
44 *  and/or winbind
45 */
46
47 #include <lber.h>
48 #include <ldap.h>
49
50 #ifndef SAM_ACCOUNT
51 #define SAM_ACCOUNT struct sam_passwd
52 #endif
53
54 extern int DEBUGLEVEL;
55
56 struct ldap_enum_info
57 {
58         LDAP *ldap_struct;
59         LDAPMessage *result;
60         LDAPMessage *entry;
61 };
62
63 static struct ldap_enum_info global_ldap_ent;
64
65
66 /*******************************************************************
67  open a connection to the ldap server.
68 ******************************************************************/
69 static BOOL
70 ldap_open_connection (LDAP ** ldap_struct)
71 {
72         int port;
73         int version, rc;
74         int tls = LDAP_OPT_X_TLS_HARD;
75         
76         if (lp_ldap_ssl() == LDAP_SSL_ON && lp_ldap_port() == 389) {
77                 port = 636;
78         }
79         else {
80                 port = lp_ldap_port();
81         }
82
83         if ((*ldap_struct = ldap_init(lp_ldap_server(), port)) == NULL) {
84                 DEBUG(0, ("The LDAP server is not responding !\n"));
85                 return (False);
86         }
87
88         /* Connect to older servers using SSL and V2 rather than Start TLS */
89         if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
90         {
91                 if (version != LDAP_VERSION2)
92                 {
93                         version = LDAP_VERSION2;
94                         ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
95                 }
96         }
97
98         switch (lp_ldap_ssl())
99         {
100                 case LDAP_SSL_START_TLS:
101                         if (ldap_get_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, 
102                                 &version) == LDAP_OPT_SUCCESS)
103                         {
104                                 if (version < LDAP_VERSION3)
105                                 {
106                                         version = LDAP_VERSION3;
107                                         ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION,
108                                                         &version);
109                                 }
110                         }
111                         if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
112                         {
113                                 DEBUG(0,
114                                       ("Failed to issue the StartTLS instruction: %s\n",
115                                        ldap_err2string(rc)));
116                                 return False;
117                         }
118                         DEBUG (2, ("StartTLS issued: using a TLS connection\n"));
119                         break;
120                 case LDAP_SSL_ON:
121                         if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
122                         {
123                                 DEBUG(0, ("Failed to setup a TLS session\n"));
124                         }
125                         break;
126                 case LDAP_SSL_OFF:
127                 default:
128         }
129
130         DEBUG(2, ("ldap_open_connection: connection opened\n"));
131         return (True);
132 }
133
134 /*******************************************************************
135  connect to the ldap server under system privilege.
136 ******************************************************************/
137 static BOOL ldap_connect_system(LDAP * ldap_struct)
138 {
139         int rc;
140         static BOOL got_pw = False;
141         static pstring ldap_secret;
142
143         /* get the password if we don't have it already */
144         if (!got_pw && !(got_pw=fetch_ldap_pw(lp_ldap_admin_dn(), ldap_secret, sizeof(pstring)))) 
145         {
146                 DEBUG(0, ("ldap_connect_system: Failed to retrieve password for %s from secrets.tdb\n",
147                         lp_ldap_admin_dn()));
148                 return False;
149         }
150
151         /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite 
152            (OpenLDAP) doesnt' seem to support it */
153         if ((rc = ldap_simple_bind_s(ldap_struct, lp_ldap_admin_dn(), 
154                 ldap_secret)) != LDAP_SUCCESS)
155         {
156                 DEBUG(0, ("Bind failed: %s\n", ldap_err2string(rc)));
157                 return (False);
158         }
159         
160         DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
161         return (True);
162 }
163
164 /*******************************************************************
165  run the search by name.
166 ******************************************************************/
167 static int ldap_search_one_user (LDAP * ldap_struct, const char *filter, LDAPMessage ** result)
168 {
169         int scope = LDAP_SCOPE_SUBTREE;
170         int rc;
171
172         DEBUG(2, ("ldap_search_one_user: searching for:[%s]\n", filter));
173
174         rc = ldap_search_s (ldap_struct, lp_ldap_suffix (), scope, 
175                 filter, NULL, 0, result);
176
177         if (rc != LDAP_SUCCESS) {
178                 DEBUG(0,("ldap_search_one_user: Problem during the LDAP search: %s\n", 
179                         ldap_err2string (rc)));
180                 DEBUG(3,("ldap_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(), 
181                         filter));
182         }
183         return (rc);
184 }
185
186 /*******************************************************************
187  run the search by name.
188 ******************************************************************/
189 static int ldap_search_one_user_by_name (LDAP * ldap_struct, const char *user,
190                              LDAPMessage ** result)
191 {
192         pstring filter;
193         
194         /*
195            in the filter expression, replace %u with the real name
196            so in ldap filter, %u MUST exist :-)
197          */
198         pstrcpy(filter, lp_ldap_filter());
199
200         /* have to use this here because $ is filtered out
201            * in pstring_sub
202          */
203         all_string_sub(filter, "%u", user, sizeof(pstring));
204
205         return ldap_search_one_user(ldap_struct, filter, result);
206 }
207
208 /*******************************************************************
209  run the search by uid.
210 ******************************************************************/
211 static int ldap_search_one_user_by_uid(LDAP * ldap_struct, int uid,
212                             LDAPMessage ** result)
213 {
214         struct passwd *user;
215         pstring filter;
216
217         /* Get the username from the system and look that up in the LDAP */
218         user = sys_getpwuid(uid);
219         pstrcpy(filter, lp_ldap_filter());
220         all_string_sub(filter, "%u", user->pw_name, sizeof(pstring));
221
222         return ldap_search_one_user(ldap_struct, filter, result);
223 }
224
225 /*******************************************************************
226  run the search by rid.
227 ******************************************************************/
228 static int ldap_search_one_user_by_rid (LDAP * ldap_struct, uint32 rid,
229                             LDAPMessage ** result)
230 {
231         pstring filter;
232         int rc;
233
234         /* check if the user rid exsists, if not, try searching on the uid */
235         snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
236         rc = ldap_search_one_user(ldap_struct, filter, result);
237         
238         if (rc != LDAP_SUCCESS)
239                 rc = ldap_search_one_user_by_uid(ldap_struct, 
240                         pdb_user_rid_to_uid(rid), result);
241
242         return rc;
243 }
244
245 /*******************************************************************
246 search an attribute and return the first value found.
247 ******************************************************************/
248 static void get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
249                      char *attribute, char *value)
250 {
251         char **valeurs;
252
253         if ((valeurs = ldap_get_values (ldap_struct, entry, attribute)) != NULL) {
254                 pstrcpy(value, valeurs[0]);
255                 ldap_value_free(valeurs);
256                 DEBUG (2, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
257         }
258         else {
259                 value = NULL;
260                 DEBUG (2, ("get_single_attribute: [%s] = [NULL]\n", attribute));
261         }
262 }
263
264 /************************************************************************
265 Routine to manage the LDAPMod structure array
266 manage memory used by the array, by each struct, and values
267
268 ************************************************************************/
269 static void make_a_mod (LDAPMod *** modlist, int modop, char *attribute, char *value)
270 {
271         LDAPMod **mods;
272         int i;
273         int j;
274
275         mods = *modlist;
276
277         if (attribute == NULL || *attribute == '\0')
278                 return;
279
280         if (value == NULL || *value == '\0')
281                 return;
282
283         if (mods == NULL) 
284         {
285                 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
286                 if (mods == NULL)
287                 {
288                         DEBUG(0, ("make_a_mod: out of memory!\n"));
289                         return;
290                 }
291                 mods[0] = NULL;
292         }
293
294         for (i = 0; mods[i] != NULL; ++i) {
295                 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
296                         break;
297         }
298
299         if (mods[i] == NULL)
300         {
301                 mods = (LDAPMod **) realloc (mods, (i + 2) * sizeof (LDAPMod *));
302                 if (mods == NULL)
303                 {
304                         DEBUG(0, ("make_a_mod: out of memory!\n"));
305                         return;
306                 }
307                 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
308                 if (mods[i] == NULL)
309                 {
310                         DEBUG(0, ("make_a_mod: out of memory!\n"));
311                         return;
312                 }
313                 mods[i]->mod_op = modop;
314                 mods[i]->mod_values = NULL;
315                 mods[i]->mod_type = strdup(attribute);
316                 mods[i + 1] = NULL;
317         }
318
319         if (value != NULL)
320         {
321                 j = 0;
322                 if (mods[i]->mod_values != NULL) {
323                         for (; mods[i]->mod_values[j] != NULL; j++);
324                 }
325                 mods[i]->mod_values = (char **)realloc(mods[i]->mod_values,
326                                                (j + 2) * sizeof (char *));
327                                                
328                 if (mods[i]->mod_values == NULL) {
329                         DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
330                         return;
331                 }
332                 mods[i]->mod_values[j] = strdup(value);
333                 mods[i]->mod_values[j + 1] = NULL;
334         }
335         *modlist = mods;
336 }
337
338 /* New Interface is being implemented here */
339
340 /**********************************************************************
341 Initialize SAM_ACCOUNT from an LDAP query
342 (Based on init_sam_from_buffer in pdb_tdb.c)
343 *********************************************************************/
344 static BOOL init_sam_from_ldap (SAM_ACCOUNT * sampass,
345                    LDAP * ldap_struct, LDAPMessage * entry)
346 {
347         time_t  logon_time,
348                         logoff_time,
349                         kickoff_time,
350                         pass_last_set_time, 
351                         pass_can_change_time, 
352                         pass_must_change_time;
353         static pstring username;
354         static pstring domain;
355         static pstring nt_username;
356         static pstring fullname;
357         static pstring homedir;
358         static pstring dir_drive;
359         static pstring logon_script;
360         static pstring profile_path;
361         static pstring acct_desc;
362         static pstring munged_dial;
363         static pstring workstations;
364         struct passwd *sys_user;
365         uint32 user_rid, group_rid;
366         static uint8 smblmpwd[16];
367         static uint8 smbntpwd[16];
368         uint16 acct_ctrl, logon_divs;
369         uint32 hours_len;
370         uint8 *hours;
371         pstring temp;
372
373         get_single_attribute(ldap_struct, entry, "uid", username);
374         DEBUG(2, ("Entry found for user: %s\n", username));
375
376         /* not sure about this for nt_username */
377         get_single_attribute (ldap_struct, entry, "sAMAccountName", nt_username);
378         if (!nt_username)
379                 pstrcpy(nt_username, username);
380
381         get_single_attribute(ldap_struct, entry, "sambaDomain", domain);
382         if (!domain)
383                 pstrcpy(domain, lp_workgroup());
384
385         get_single_attribute(ldap_struct, entry, "pwdLastSet", temp);
386         pass_last_set_time = (time_t) strtol(temp, NULL, 16);
387
388         get_single_attribute(ldap_struct, entry, "logonTime", temp);
389         logon_time = (time_t) strtol(temp, NULL, 16);
390
391         get_single_attribute(ldap_struct, entry, "logoffTime", temp);
392         logoff_time = (time_t) strtol(temp, NULL, 16);
393
394         get_single_attribute(ldap_struct, entry, "kickoffTime", temp);
395         kickoff_time = (time_t) strtol(temp, NULL, 16);
396
397         get_single_attribute(ldap_struct, entry, "pwdCanChange", temp);
398         pass_can_change_time = (time_t) strtol(temp, NULL, 16);
399
400         get_single_attribute(ldap_struct, entry, "pwdMustChange", temp);
401         pass_must_change_time = (time_t) strtol(temp, NULL, 16);
402
403         /* recommend that 'gecos' and 'displayName' should refer to the same
404            * attribute OID.  userFullName depreciated, only used by Samba
405            * primary rules of LDAP: don't make a new attribute when one is already defined
406            * that fits your needs; using gecos then displayName then cn rather than 'userFullName'
407          */
408
409         get_single_attribute(ldap_struct, entry, "gecos", fullname);
410
411         if (!fullname) {
412                 get_single_attribute(ldap_struct, entry, "displayName", fullname);
413                 get_single_attribute(ldap_struct, entry, "cn", fullname);
414         }
415
416         get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive);
417         get_single_attribute(ldap_struct, entry, "scriptPath", logon_script);
418         get_single_attribute(ldap_struct, entry, "profilePath", profile_path);
419         get_single_attribute(ldap_struct, entry, "description", acct_desc);
420         get_single_attribute (ldap_struct, entry, "userWorkstations", workstations);
421
422         get_single_attribute(ldap_struct, entry, "rid", temp);
423         user_rid = (uint32)strtol(temp, NULL, 16);
424         get_single_attribute(ldap_struct, entry, "primaryGroupID", temp);
425         group_rid = (uint32)strtol(temp, NULL, 16);
426
427
428         /* These values MAY be in LDAP, but they can also be retrieved through 
429            *  sys_getpw*() which is how we're doing it (if you use nss_ldap, then 
430            *  these values will be stored in LDAP as well, but if not, we want the
431            *  local values to override the LDAP for this anyway 
432            *  homeDirectory attribute
433          */
434         sys_user = sys_getpwnam(username);
435         if (sys_user == NULL)
436                 return False;
437         pstrcpy(homedir, sys_user->pw_dir);
438
439
440         /* FIXME: hours stuff should be cleaner */
441         logon_divs = 168;
442         hours_len = 21;
443         hours = malloc(sizeof(hours) * hours_len);
444         memset(hours, 0xff, hours_len);
445
446         get_single_attribute (ldap_struct, entry, "lmPassword", temp);
447         pdb_gethexpwd(temp, smblmpwd);
448         memset((char *)temp, '\0', sizeof(temp));
449         get_single_attribute (ldap_struct, entry, "ntPassword", temp);
450         pdb_gethexpwd(temp, smbntpwd);
451         memset((char *)temp, '\0', sizeof(temp));
452         get_single_attribute (ldap_struct, entry, "acctFlags", temp);
453         acct_ctrl = pdb_decode_acct_ctrl(temp);
454
455         if (acct_ctrl == 0)
456                 acct_ctrl |= ACB_NORMAL;
457
458
459         pdb_set_acct_ctrl(sampass, acct_ctrl);
460         pdb_set_logon_time(sampass, logon_time);
461         pdb_set_logoff_time(sampass, logoff_time);
462         pdb_set_kickoff_time(sampass, kickoff_time);
463         pdb_set_pass_can_change_time(sampass, pass_can_change_time);
464         pdb_set_pass_must_change_time(sampass, pass_must_change_time);
465         pdb_set_pass_last_set_time(sampass, pass_last_set_time);
466
467         pdb_set_hours_len(sampass, hours_len);
468         pdb_set_logons_divs(sampass, logon_divs);
469
470         pdb_set_uid(sampass, sys_user->pw_uid);
471         pdb_set_gid(sampass, sys_user->pw_gid);
472         pdb_set_user_rid(sampass, user_rid);
473         pdb_set_group_rid(sampass, group_rid);
474
475         pdb_set_username(sampass, username);
476
477         pdb_set_domain(sampass, domain);
478         pdb_set_nt_username(sampass, nt_username);
479
480         pdb_set_fullname(sampass, fullname);
481
482         pdb_set_logon_script(sampass, logon_script);
483         pdb_set_profile_path(sampass, profile_path);
484         pdb_set_dir_drive(sampass, dir_drive);
485         pdb_set_homedir(sampass, homedir);
486         pdb_set_acct_desc(sampass, acct_desc);
487         pdb_set_workstations(sampass, workstations);
488         pdb_set_munged_dial(sampass, munged_dial);
489         pdb_set_nt_passwd(sampass, smbntpwd);
490         pdb_set_lanman_passwd(sampass, smblmpwd);
491
492         /* pdb_set_unknown_3(sampass, unknown3); */
493         /* pdb_set_unknown_5(sampass, unknown5); */
494         /* pdb_set_unknown_6(sampass, unknown6); */
495
496         pdb_set_hours(sampass, hours);
497
498         return True;
499 }
500
501 /**********************************************************************
502 Initialize SAM_ACCOUNT from an LDAP query
503 (Based on init_buffer_from_sam in pdb_tdb.c)
504 *********************************************************************/
505 static BOOL init_ldap_from_sam (LDAPMod *** mods, int ldap_state, SAM_ACCOUNT * sampass)
506 {
507         pstring temp;
508
509         *mods = NULL;
510
511         /* 
512          * took out adding "objectclass: sambaAccount"
513          * do this on a per-mod basis
514          */
515
516
517         make_a_mod(mods, ldap_state, "uid", pdb_get_username(sampass));
518         DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
519
520         /* not sure about using this for the nt_username */
521         make_a_mod (mods, ldap_state, "sAMAccountName", pdb_get_nt_username(sampass));
522         make_a_mod(mods, ldap_state, "sambaDomain", pdb_get_domain(sampass));
523
524         slprintf(temp, sizeof(temp) - 1, "%i", pdb_get_uid(sampass));
525         make_a_mod(mods, ldap_state, "uidNumber", temp);
526
527         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
528         make_a_mod(mods, ldap_state, "pwdLastSet", temp);
529
530         slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
531         make_a_mod(mods, ldap_state, "logonTime", temp);
532
533         slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
534         make_a_mod(mods, ldap_state, "logoffTime", temp);
535
536         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
537         make_a_mod(mods, ldap_state, "kickoffTime", temp);
538
539         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
540         make_a_mod(mods, ldap_state, "pwdCanChange", temp);
541
542         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
543         make_a_mod(mods, ldap_state, "pwdMustChange", temp);
544
545         /* displayName, cn, and gecos should all be the same
546            *  most easily accomplished by giving them the same OID
547            *  gecos isn't set here b/c it should be handled by the 
548            *  add-user script
549          */
550
551         make_a_mod(mods, ldap_state, "displayName", pdb_get_fullname(sampass));
552         make_a_mod(mods, ldap_state, "cn", pdb_get_fullname(sampass));
553
554         make_a_mod(mods, ldap_state, "homeDirectory", pdb_get_homedir(sampass));
555         make_a_mod(mods, ldap_state, "homeDrive", pdb_get_dirdrive(sampass));
556         make_a_mod(mods, ldap_state, "scriptPath", pdb_get_logon_script(sampass));
557         make_a_mod(mods, ldap_state, "profilePath", pdb_get_profile_path(sampass));
558         make_a_mod(mods, ldap_state, "description", pdb_get_acct_desc(sampass));
559         make_a_mod(mods, ldap_state, "userWorkstations", pdb_get_workstations(sampass));
560
561         slprintf(temp, sizeof(temp) - 1, "%i", sampass->user_rid);
562         make_a_mod(mods, ldap_state, "rid", temp);
563
564         slprintf(temp, sizeof(temp) - 1, "%i", sampass->group_rid);
565         make_a_mod(mods, ldap_state, "primaryGroupID", temp);
566
567         /* FIXME: Hours stuff goes in LDAP  */
568         pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass));
569         make_a_mod (mods, ldap_state, "lmPassword", temp);
570         pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
571         make_a_mod (mods, ldap_state, "ntPassword", temp);
572         make_a_mod (mods, ldap_state, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
573                 NEW_PW_FORMAT_SPACE_PADDED_LEN));
574
575         return True;
576 }
577
578 /**********************************************************************
579 Connect to LDAP server for password enumeration
580 *********************************************************************/
581 BOOL pdb_setsampwent(BOOL update)
582 {
583         int rc;
584         pstring filter;
585
586         if (!ldap_open_connection(&global_ldap_ent.ldap_struct))
587         {
588                 return False;
589         }
590         if (!ldap_connect_system(global_ldap_ent.ldap_struct))
591         {
592                 ldap_unbind(global_ldap_ent.ldap_struct);
593                 return False;
594         }
595
596         pstrcpy(filter, lp_ldap_filter());
597         all_string_sub(filter, "%u", "*", sizeof(pstring));
598
599         rc = ldap_search_s(global_ldap_ent.ldap_struct, lp_ldap_suffix(),
600                            LDAP_SCOPE_SUBTREE, filter, NULL, 0,
601                            &global_ldap_ent.result);
602
603         if (rc != LDAP_SUCCESS)
604         {
605                 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
606                 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
607                 ldap_msgfree(global_ldap_ent.result);
608                 ldap_unbind(global_ldap_ent.ldap_struct);
609                 global_ldap_ent.ldap_struct = NULL;
610                 global_ldap_ent.result = NULL;
611                 return False;
612         }
613
614         DEBUG(2, ("pdb_setsampwent: %d entries in the base!\n",
615                 ldap_count_entries(global_ldap_ent.ldap_struct,
616                 global_ldap_ent.result)));
617
618         global_ldap_ent.entry = ldap_first_entry(global_ldap_ent.ldap_struct,
619                                  global_ldap_ent.result);
620
621         return True;
622 }
623
624 /**********************************************************************
625 End enumeration of the LDAP password list 
626 *********************************************************************/
627 void pdb_endsampwent(void)
628 {
629         if (global_ldap_ent.ldap_struct && global_ldap_ent.result)
630         {
631                 ldap_msgfree(global_ldap_ent.result);
632                 ldap_unbind(global_ldap_ent.ldap_struct);
633                 global_ldap_ent.ldap_struct = NULL;
634                 global_ldap_ent.result = NULL;
635         }
636 }
637
638 /**********************************************************************
639 Get the next entry in the LDAP password database 
640 *********************************************************************/
641 BOOL pdb_getsampwent(SAM_ACCOUNT * user)
642 {
643         if (!global_ldap_ent.entry)
644                 return False;
645
646         global_ldap_ent.entry = ldap_next_entry(global_ldap_ent.ldap_struct,
647                                 global_ldap_ent.entry);
648
649         if (global_ldap_ent.entry != NULL)
650         {
651                 return init_sam_from_ldap(user, global_ldap_ent.ldap_struct,
652                                           global_ldap_ent.entry);
653         }
654         return False;
655 }
656
657 /**********************************************************************
658 Get SAM_ACCOUNT entry from LDAP by username 
659 *********************************************************************/
660 BOOL pdb_getsampwnam(SAM_ACCOUNT * user, char *sname)
661 {
662         LDAP *ldap_struct;
663         LDAPMessage *result;
664         LDAPMessage *entry;
665
666         if (!ldap_open_connection(&ldap_struct))
667                 return False;
668         if (!ldap_connect_system(ldap_struct))
669         {
670                 ldap_unbind(ldap_struct);
671                 return False;
672         }
673         if (ldap_search_one_user_by_name(ldap_struct, sname, &result) !=
674             LDAP_SUCCESS)
675         {
676                 ldap_unbind(ldap_struct);
677                 return False;
678         }
679         if (ldap_count_entries(ldap_struct, result) < 1)
680         {
681                 DEBUG(0,
682                       ("We don't find this user [%s] count=%d\n", sname,
683                        ldap_count_entries(ldap_struct, result)));
684                 ldap_unbind(ldap_struct);
685                 return False;
686         }
687         entry = ldap_first_entry(ldap_struct, result);
688         if (entry)
689         {
690                 init_sam_from_ldap(user, ldap_struct, entry);
691                 ldap_msgfree(result);
692                 ldap_unbind(ldap_struct);
693                 return True;
694         }
695         else
696         {
697                 ldap_msgfree(result);
698                 ldap_unbind(ldap_struct);
699                 return False;
700         }
701 }
702
703 /**********************************************************************
704 Get SAM_ACCOUNT entry from LDAP by rid 
705 *********************************************************************/
706 BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid)
707 {
708         LDAP *ldap_struct;
709         LDAPMessage *result;
710         LDAPMessage *entry;
711
712         if (!ldap_open_connection(&ldap_struct))
713                 return False;
714
715         if (!ldap_connect_system(ldap_struct))
716         {
717                 ldap_unbind(ldap_struct);
718                 return False;
719         }
720         if (ldap_search_one_user_by_rid(ldap_struct, rid, &result) !=
721             LDAP_SUCCESS)
722         {
723                 ldap_unbind(ldap_struct);
724                 return False;
725         }
726
727         if (ldap_count_entries(ldap_struct, result) < 1)
728         {
729                 DEBUG(0,
730                       ("We don't find this rid [%i] count=%d\n", rid,
731                        ldap_count_entries(ldap_struct, result)));
732                 ldap_unbind(ldap_struct);
733                 return False;
734         }
735
736         entry = ldap_first_entry(ldap_struct, result);
737         if (entry)
738         {
739                 init_sam_from_ldap(user, ldap_struct, entry);
740                 ldap_msgfree(result);
741                 ldap_unbind(ldap_struct);
742                 return True;
743         }
744         else
745         {
746                 ldap_msgfree(result);
747                 ldap_unbind(ldap_struct);
748                 return False;
749         }
750 }
751
752 /**********************************************************************
753  Get SAM_ACCOUNT entry from LDAP by uid 
754 *********************************************************************/
755 BOOL pdb_getsampwuid(SAM_ACCOUNT * user, uid_t uid)
756 {
757         LDAP *ldap_struct;
758         LDAPMessage *result;
759         LDAPMessage *entry;
760
761         if (!ldap_open_connection(&ldap_struct))
762                 return False;
763
764         if (!ldap_connect_system(ldap_struct))
765         {
766                 ldap_unbind(ldap_struct);
767                 return False;
768         }
769         if (ldap_search_one_user_by_uid(ldap_struct, uid, &result) !=
770             LDAP_SUCCESS)
771         {
772                 ldap_unbind(ldap_struct);
773                 return False;
774         }
775
776         if (ldap_count_entries(ldap_struct, result) < 1)
777         {
778                 DEBUG(0,
779                       ("We don't find this uid [%i] count=%d\n", uid,
780                        ldap_count_entries(ldap_struct, result)));
781                 ldap_unbind(ldap_struct);
782                 return False;
783         }
784         entry = ldap_first_entry(ldap_struct, result);
785         if (entry)
786         {
787                 init_sam_from_ldap(user, ldap_struct, entry);
788                 ldap_msgfree(result);
789                 ldap_unbind(ldap_struct);
790                 return True;
791         }
792         else
793         {
794                 ldap_msgfree(result);
795                 ldap_unbind(ldap_struct);
796                 return False;
797         }
798 }
799
800
801 /**********************************************************************
802 Delete entry from LDAP for username 
803 *********************************************************************/
804 BOOL pdb_delete_sam_account(char *sname)
805 {
806         int rc;
807         char *dn;
808         LDAP *ldap_struct;
809         LDAPMessage *entry;
810         LDAPMessage *result;
811
812         if (!ldap_open_connection (&ldap_struct))
813                 return False;
814
815         DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
816         
817         if (!ldap_connect_system (ldap_struct)) {
818                 ldap_unbind (ldap_struct);
819                 DEBUG(0, ("Failed to delete user %s from LDAP.\n", sname));
820                 return False;
821         }
822
823         rc = ldap_search_one_user_by_name (ldap_struct, sname, &result);
824         if (ldap_count_entries (ldap_struct, result) == 0) {
825                 DEBUG (0, ("User doesn't exit!\n"));
826                 ldap_msgfree (result);
827                 ldap_unbind (ldap_struct);
828                 return False;
829         }
830
831         entry = ldap_first_entry (ldap_struct, result);
832         dn = ldap_get_dn (ldap_struct, entry);
833
834         rc = ldap_delete_s (ldap_struct, dn);
835
836         ldap_memfree (dn);
837         if (rc != LDAP_SUCCESS) {
838                 char *ld_error;
839                 ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
840                 DEBUG (0,("failed to delete user with uid = %s with: %s\n\t%s\n",
841                         sname, ldap_err2string (rc), ld_error));
842                 free (ld_error);
843                 ldap_unbind (ldap_struct);
844                 return False;
845         }
846
847         DEBUG (2,("successfully deleted uid = %s from the LDAP database\n", sname));
848         ldap_unbind (ldap_struct);
849         return True;
850 }
851
852 /**********************************************************************
853 Update SAM_ACCOUNT 
854 *********************************************************************/
855 BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd, BOOL override)
856 {
857         int rc;
858         char *dn;
859         LDAP *ldap_struct;
860         LDAPMessage *result;
861         LDAPMessage *entry;
862         LDAPMod **mods;
863
864         if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */
865                 return False;
866
867         if (!ldap_connect_system(ldap_struct))  /* connect as system account */
868         {
869                 ldap_unbind(ldap_struct);
870                 return False;
871         }
872
873         rc = ldap_search_one_user_by_name(ldap_struct,
874                                           pdb_get_username(newpwd), &result);
875
876         if (ldap_count_entries(ldap_struct, result) == 0)
877         {
878                 DEBUG(0, ("No user to modify!\n"));
879                 ldap_msgfree(result);
880                 ldap_unbind(ldap_struct);
881                 return False;
882         }
883
884         init_ldap_from_sam(&mods, LDAP_MOD_REPLACE, newpwd);
885
886         entry = ldap_first_entry(ldap_struct, result);
887         dn = ldap_get_dn(ldap_struct, entry);
888
889         rc = ldap_modify_s(ldap_struct, dn, mods);
890
891         if (rc != LDAP_SUCCESS)
892         {
893                 char *ld_error;
894                 ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING,
895                                 &ld_error);
896                 DEBUG(0,
897                       ("failed to modify user with uid = %s with: %s\n\t%s\n",
898                        pdb_get_username(newpwd), ldap_err2string(rc),
899                        ld_error));
900                 free(ld_error);
901                 ldap_unbind(ldap_struct);
902                 return False;
903         }
904
905         DEBUG(2,
906               ("successfully modified uid = %s in the LDAP database\n",
907                pdb_get_username(newpwd)));
908         ldap_mods_free(mods, 1);
909         ldap_unbind(ldap_struct);
910         return True;
911 }
912
913 /**********************************************************************
914 Add SAM_ACCOUNT to LDAP 
915 *********************************************************************/
916 BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd)
917 {
918         int rc;
919         pstring filter;
920         LDAP *ldap_struct;
921         LDAPMessage *result;
922         pstring dn;
923         LDAPMod **mods;
924         int ldap_op = LDAP_MOD_ADD;
925
926         if (!ldap_open_connection(&ldap_struct))        /* open a connection to the server */
927         {
928                 return False;
929         }
930
931         if (!ldap_connect_system(ldap_struct))  /* connect as system account */
932         {
933                 ldap_unbind(ldap_struct);
934                 return False;
935         }
936
937         if (pdb_get_username(newpwd) != NULL) {
938                 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", 
939                         pdb_get_username(newpwd), lp_ldap_suffix ());
940         }
941         else
942         {
943                 return False;
944         }
945
946
947         rc = ldap_search_one_user_by_name (ldap_struct, pdb_get_username(newpwd), &result);
948
949         if (ldap_count_entries(ldap_struct, result) != 0)
950         {
951                 DEBUG(0,("User already in the base, with samba properties\n"));
952                 ldap_msgfree(result);
953                 ldap_unbind(ldap_struct);
954                 return False;
955         }
956         ldap_msgfree(result);
957
958         slprintf (filter, sizeof (filter) - 1, "uid=%s", pdb_get_username(newpwd));
959         rc = ldap_search_one_user(ldap_struct, filter, &result);
960         if (ldap_count_entries(ldap_struct, result) == 1)
961         {
962                 char *tmp;
963                 LDAPMessage *entry;
964                 DEBUG(3,("User exists without samba properties: adding them\n"));
965                 ldap_op = LDAP_MOD_REPLACE;
966                 entry = ldap_first_entry (ldap_struct, result);
967                 tmp = ldap_get_dn (ldap_struct, entry);
968                 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
969                 ldap_memfree (tmp);
970         }
971         else
972         {
973                 DEBUG (3, ("More than one user with that uid exists: bailing out!\n"));
974                 return False;
975         }
976
977         ldap_msgfree(result);
978
979         init_ldap_from_sam(&mods, ldap_op, newpwd);
980         make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
981
982         if (ldap_op == LDAP_MOD_REPLACE) {
983                 rc = ldap_modify_s(ldap_struct, dn, mods);
984         }
985         else {
986                 rc = ldap_add_s(ldap_struct, dn, mods);
987         }
988
989         if (rc != LDAP_SUCCESS)
990         {
991                 char *ld_error;
992
993                 ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
994                 DEBUG(0,("failed to modify user with uid = %s with: %s\n\t%s\n",
995                         pdb_get_username(newpwd), ldap_err2string (rc), ld_error));
996                 free(ld_error);
997                 ldap_mods_free(mods, 1);
998                 ldap_unbind(ldap_struct);
999                 return False;
1000         }
1001         
1002         DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
1003         ldap_mods_free(mods, 1);
1004         ldap_unbind(ldap_struct);
1005         return True;
1006 }
1007
1008 #else
1009 void dummy_function(void);
1010 void
1011 dummy_function (void)
1012 {
1013 }                               /* stop some compilers complaining */
1014 #endif