Only reterive the attributes we are actually going to use - rather than
[tprouty/samba.git] / source3 / passdb / pdb_ldap.c
1 /* 
2    Unix SMB/CIFS implementation.
3    LDAP protocol helper functions for SAMBA
4    Copyright (C) Gerald Carter 2001
5    Copyright (C) Shahms King 2001
6    Copyright (C) Jean François Micouleau 1998
7    Copyright (C) Andrew Bartlett 2002
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22    
23 */
24
25 #include "includes.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_PASSDB
29
30 #ifdef HAVE_LDAP
31 /* TODO:
32 *  persistent connections: if using NSS LDAP, many connections are made
33 *      however, using only one within Samba would be nice
34 *  
35 *  Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
36 *
37 *  Other LDAP based login attributes: accountExpires, etc.
38 *  (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
39 *  structures don't have fields for some of these attributes)
40 *
41 *  SSL is done, but can't get the certificate based authentication to work
42 *  against on my test platform (Linux 2.4, OpenLDAP 2.x)
43 */
44
45 /* NOTE: this will NOT work against an Active Directory server
46 *  due to the fact that the two password fields cannot be retrieved
47 *  from a server; recommend using security = domain in this situation
48 *  and/or winbind
49 */
50
51 #include <lber.h>
52 #include <ldap.h>
53
54 #ifndef SAM_ACCOUNT
55 #define SAM_ACCOUNT struct sam_passwd
56 #endif
57
58 struct ldapsam_privates {
59
60         /* Former statics */
61         LDAP *ldap_struct;
62         LDAPMessage *result;
63         LDAPMessage *entry;
64         int index;
65         
66         /* retrive-once info */
67         const char *uri;
68         
69         BOOL permit_non_unix_accounts;
70         
71         uint32 low_nua_rid; 
72         uint32 high_nua_rid; 
73 };
74
75 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
76
77 /*******************************************************************
78  find the ldap password
79 ******************************************************************/
80 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
81 {
82         char *key = NULL;
83         size_t size;
84         
85         *dn = smb_xstrdup(lp_ldap_admin_dn());
86         
87         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
88                 SAFE_FREE(*dn);
89                 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
90         }
91         
92         *pw=secrets_fetch(key, &size);
93         if (!size) {
94                 /* Upgrade 2.2 style entry */
95                 char *p;
96                 char* old_style_key = strdup(*dn);
97                 char *data;
98                 fstring old_style_pw;
99                 
100                 if (!old_style_key) {
101                         DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
102                         return False;
103                 }
104
105                 for (p=old_style_key; *p; p++)
106                         if (*p == ',') *p = '/';
107         
108                 data=secrets_fetch(old_style_key, &size);
109                 if (!size && size < sizeof(old_style_pw)) {
110                         DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
111                         SAFE_FREE(old_style_key);
112                         SAFE_FREE(*dn);
113                         return False;
114                 }
115
116                 strncpy(old_style_pw, data, size);
117                 old_style_pw[size] = 0;
118
119                 SAFE_FREE(data);
120
121                 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
122                         DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
123                         SAFE_FREE(old_style_key);
124                         SAFE_FREE(*dn);
125                         return False;                   
126                 }
127                 if (!secrets_delete(old_style_key)) {
128                         DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
129                 }
130
131                 SAFE_FREE(old_style_key);
132
133                 *pw = smb_xstrdup(old_style_pw);                
134         }
135         
136         return True;
137 }
138
139 char *attr[] = {"uid", "pwdLastSet", "logonTime",
140                 "logoffTime", "kickoffTime", "cn",
141                 "pwdCanChange", "pwdMustChange",
142                 "dislplayName", "homeDrive",
143                 "smbHome", "scriptPath",
144                 "profilePath", "description",
145                 "userWorkstation", "rid",
146                 "primaryGroupID", "lmPassword",
147                 "ntPassword", "acctFlags",
148                 "domain", "description", NULL };
149
150 /*******************************************************************
151  open a connection to the ldap server.
152 ******************************************************************/
153 static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
154 {
155
156         if (geteuid() != 0) {
157                 DEBUG(0, ("ldap_open_connection: cannot access LDAP when not root..\n"));
158                 return False;
159         }
160         
161 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
162         DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
163         
164         if (ldap_initialize(ldap_struct, ldap_state->uri) != LDAP_SUCCESS) {
165                 DEBUG(0, ("ldap_initialize: %s\n", strerror(errno)));
166                 return (False);
167         }
168 #else 
169
170         /* Parse the string manually */
171
172         {
173                 int rc;
174                 int tls = LDAP_OPT_X_TLS_HARD;
175                 int port = 0;
176                 int version;
177                 fstring protocol;
178                 fstring host;
179                 const char *p = ldap_state->uri; 
180                 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
181                 
182                 /* skip leading "URL:" (if any) */
183                 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
184                         p += 4;
185                 }
186
187                 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
188                 
189                 if (port == 0) {
190                         if (strequal(protocol, "ldap")) {
191                                 port = LDAP_PORT;
192                         } else if (strequal(protocol, "ldaps")) {
193                                 port = LDAPS_PORT;
194                         } else {
195                                 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
196                         }
197                 }
198
199                 if ((*ldap_struct = ldap_init(host, port)) == NULL)     {
200                         DEBUG(0, ("ldap_init failed !\n"));
201                         return False;
202                 }
203
204                 /* Connect to older servers using SSL and V2 rather than Start TLS */
205                 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
206                 {
207                         if (version != LDAP_VERSION2)
208                         {
209                                 version = LDAP_VERSION2;
210                                 ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
211                         }
212                 }
213
214                 if (strequal(protocol, "ldaps")) { 
215                         if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
216                                 if (ldap_get_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, 
217                                                      &version) == LDAP_OPT_SUCCESS)
218                                 {
219                                         if (version < LDAP_VERSION3)
220                                         {
221                                                 version = LDAP_VERSION3;
222                                                 ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION,
223                                                                  &version);
224                                         }
225                                 }
226                                 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
227                                 {
228                                         DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
229                                                  ldap_err2string(rc)));
230                                         return False;
231                                 }
232                                 DEBUG (2, ("StartTLS issued: using a TLS connection\n"));
233                         } else {
234                                 
235                                 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
236                                 {
237                                         DEBUG(0, ("Failed to setup a TLS session\n"));
238                                 }
239                         }
240                 } else {
241                         /* 
242                          * No special needs to setup options prior to the LDAP
243                          * bind (which should be called next via ldap_connect_system()
244                          */
245                 }
246         }
247 #endif
248
249         DEBUG(2, ("ldap_open_connection: connection opened\n"));
250         return True;
251 }
252
253
254 /*******************************************************************
255  Add a rebind function for authenticated referrals
256 ******************************************************************/
257
258 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
259                        int *method, int freeit )
260 {
261         int rc;
262         char *ldap_dn;
263         char *ldap_secret;
264         
265         /** @TODO Should we be doing something to check what servers we rebind to?
266             Could we get a referral to a machine that we don't want to give our
267             username and password to? */
268         
269         if (freeit != 0)
270         {
271                 
272                 if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret)) 
273                 {
274                         DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
275                         return LDAP_OPERATIONS_ERROR;  /* No idea what to return */
276                 }
277                 
278                 DEBUG(5,("ldap_connect_system: Rebinding as \"%s\"\n", 
279                           ldap_dn));
280
281                 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
282                 
283                 SAFE_FREE(ldap_dn);
284                 SAFE_FREE(ldap_secret);
285
286                 return rc;
287         }
288         return 0;
289 }
290
291 /*******************************************************************
292  connect to the ldap server under system privilege.
293 ******************************************************************/
294 static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
295 {
296         int rc;
297         char *ldap_dn;
298         char *ldap_secret;
299
300         /* get the password */
301         if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
302         {
303                 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
304                 return False;
305         }
306
307         /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite 
308            (OpenLDAP) doesnt' seem to support it */
309            
310         DEBUG(10,("ldap_connect_system: Binding to ldap server as \"%s\"\n",
311                 ldap_dn));
312         
313         ldap_set_rebind_proc(ldap_struct, (LDAP_REBIND_PROC *)(&rebindproc));   
314
315         rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
316
317         SAFE_FREE(ldap_dn);
318         SAFE_FREE(ldap_secret);
319
320         if (rc != LDAP_SUCCESS)
321         {
322                 DEBUG(0, ("Bind failed: %s\n", ldap_err2string(rc)));
323                 return False;
324         }
325         
326         DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
327         return True;
328 }
329
330 /*******************************************************************
331  run the search by name.
332 ******************************************************************/
333 static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, LDAP * ldap_struct, const char *filter, LDAPMessage ** result)
334 {
335         int scope = LDAP_SCOPE_SUBTREE;
336         int rc;
337
338         DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
339
340         rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, attr, 0, result);
341
342         if (rc != LDAP_SUCCESS) {
343                 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s\n", 
344                         ldap_err2string (rc)));
345                 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(), 
346                         filter));
347         }
348         
349         return rc;
350 }
351
352 /*******************************************************************
353  run the search by name.
354 ******************************************************************/
355 static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, LDAP * ldap_struct, const char *user,
356                              LDAPMessage ** result)
357 {
358         pstring filter;
359         
360         /*
361          * in the filter expression, replace %u with the real name
362          * so in ldap filter, %u MUST exist :-)
363          */
364         pstrcpy(filter, lp_ldap_filter());
365
366         /* 
367          * have to use this here because $ is filtered out
368            * in pstring_sub
369          */
370         all_string_sub(filter, "%u", user, sizeof(pstring));
371
372         return ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
373 }
374
375 /*******************************************************************
376  run the search by uid.
377 ******************************************************************/
378 static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state, 
379                                           LDAP * ldap_struct, int uid,
380                                           LDAPMessage ** result)
381 {
382         struct passwd *user;
383         pstring filter;
384
385         /* Get the username from the system and look that up in the LDAP */
386         
387         if ((user = getpwuid_alloc(uid)) == NULL) {
388                 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid));
389                 return LDAP_NO_SUCH_OBJECT;
390         }
391         
392         pstrcpy(filter, lp_ldap_filter());
393         
394         all_string_sub(filter, "%u", user->pw_name, sizeof(pstring));
395
396         passwd_free(&user);
397
398         return ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
399 }
400
401 /*******************************************************************
402  run the search by rid.
403 ******************************************************************/
404 static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state, 
405                                            LDAP * ldap_struct, uint32 rid,
406                                            LDAPMessage ** result)
407 {
408         pstring filter;
409         int rc;
410
411         /* check if the user rid exsists, if not, try searching on the uid */
412         
413         snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
414         rc = ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
415         
416         if (rc != LDAP_SUCCESS)
417                 rc = ldapsam_search_one_user_by_uid(ldap_state, ldap_struct, 
418                                                     fallback_pdb_user_rid_to_uid(rid), 
419                                                     result);
420
421         return rc;
422 }
423
424 /*******************************************************************
425 search an attribute and return the first value found.
426 ******************************************************************/
427 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
428                                   char *attribute, pstring value)
429 {
430         char **values;
431
432         if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
433                 value = NULL;
434                 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
435                 
436                 return False;
437         }
438         
439         pstrcpy(value, values[0]);
440         ldap_value_free(values);
441 #ifdef DEBUG_PASSWORDS
442         DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
443 #endif  
444         return True;
445 }
446
447 /************************************************************************
448 Routine to manage the LDAPMod structure array
449 manage memory used by the array, by each struct, and values
450
451 ************************************************************************/
452 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
453 {
454         LDAPMod **mods;
455         int i;
456         int j;
457
458         mods = *modlist;
459
460         if (attribute == NULL || *attribute == '\0')
461                 return;
462
463         if (value == NULL || *value == '\0')
464                 return;
465
466         if (mods == NULL) 
467         {
468                 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
469                 if (mods == NULL)
470                 {
471                         DEBUG(0, ("make_a_mod: out of memory!\n"));
472                         return;
473                 }
474                 mods[0] = NULL;
475         }
476
477         for (i = 0; mods[i] != NULL; ++i) {
478                 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
479                         break;
480         }
481
482         if (mods[i] == NULL)
483         {
484                 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
485                 if (mods == NULL)
486                 {
487                         DEBUG(0, ("make_a_mod: out of memory!\n"));
488                         return;
489                 }
490                 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
491                 if (mods[i] == NULL)
492                 {
493                         DEBUG(0, ("make_a_mod: out of memory!\n"));
494                         return;
495                 }
496                 mods[i]->mod_op = modop;
497                 mods[i]->mod_values = NULL;
498                 mods[i]->mod_type = strdup(attribute);
499                 mods[i + 1] = NULL;
500         }
501
502         if (value != NULL)
503         {
504                 j = 0;
505                 if (mods[i]->mod_values != NULL) {
506                         for (; mods[i]->mod_values[j] != NULL; j++);
507                 }
508                 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
509                                                (j + 2) * sizeof (char *));
510                                                
511                 if (mods[i]->mod_values == NULL) {
512                         DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
513                         return;
514                 }
515                 mods[i]->mod_values[j] = strdup(value);
516                 mods[i]->mod_values[j + 1] = NULL;
517         }
518         *modlist = mods;
519 }
520
521 /* New Interface is being implemented here */
522
523 /**********************************************************************
524 Initialize SAM_ACCOUNT from an LDAP query
525 (Based on init_sam_from_buffer in pdb_tdb.c)
526 *********************************************************************/
527 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, 
528                                 SAM_ACCOUNT * sampass,
529                                 LDAP * ldap_struct, LDAPMessage * entry)
530 {
531         time_t  logon_time,
532                         logoff_time,
533                         kickoff_time,
534                         pass_last_set_time, 
535                         pass_can_change_time, 
536                         pass_must_change_time;
537         pstring         username, 
538                         domain,
539                         nt_username,
540                         fullname,
541                         homedir,
542                         dir_drive,
543                         logon_script,
544                         profile_path,
545                         acct_desc,
546                         munged_dial,
547                         workstations;
548         struct passwd   *pw;
549         uint32          user_rid, 
550                         group_rid;
551         uint8           smblmpwd[16],
552                         smbntpwd[16];
553         uint16          acct_ctrl, 
554                         logon_divs;
555         uint32 hours_len;
556         uint8           hours[MAX_HOURS_LEN];
557         pstring temp;
558         uid_t           uid = -1;
559         gid_t           gid = getegid();
560
561
562         /*
563          * do a little initialization
564          */
565         username[0]     = '\0';
566         domain[0]       = '\0';
567         nt_username[0]  = '\0';
568         fullname[0]     = '\0';
569         homedir[0]      = '\0';
570         dir_drive[0]    = '\0';
571         logon_script[0] = '\0';
572         profile_path[0] = '\0';
573         acct_desc[0]    = '\0';
574         munged_dial[0]  = '\0';
575         workstations[0] = '\0';
576          
577
578         if (sampass == NULL || ldap_struct == NULL || entry == NULL) {
579                 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
580                 return False;
581         }
582
583         get_single_attribute(ldap_struct, entry, "uid", username);
584         DEBUG(2, ("Entry found for user: %s\n", username));
585
586         pstrcpy(nt_username, username);
587
588         pstrcpy(domain, lp_workgroup());
589
590         get_single_attribute(ldap_struct, entry, "rid", temp);
591         user_rid = (uint32)atol(temp);
592         if (!get_single_attribute(ldap_struct, entry, "primaryGroupID", temp)) {
593                 group_rid = 0;
594         } else {
595                 group_rid = (uint32)atol(temp);
596         }
597
598         if ((ldap_state->permit_non_unix_accounts) 
599             && (user_rid >= ldap_state->low_nua_rid)
600             && (user_rid <= ldap_state->high_nua_rid)) {
601                 
602         } else {
603                 
604                 /* These values MAY be in LDAP, but they can also be retrieved through 
605                  *  sys_getpw*() which is how we're doing it 
606                  */
607         
608                 pw = getpwnam_alloc(username);
609                 if (pw == NULL) {
610                         DEBUG (2,("init_sam_from_ldap: User [%s] does not ave a uid!\n", username));
611                         return False;
612                 }
613                 uid = pw->pw_uid;
614                 gid = pw->pw_gid;
615
616                 pdb_set_unix_homedir(sampass, pw->pw_dir);
617
618                 passwd_free(&pw);
619
620                 pdb_set_uid(sampass, uid);
621                 pdb_set_gid(sampass, gid);
622
623                 if (group_rid == 0) {
624                         GROUP_MAP map;
625                         /* call the mapping code here */
626                         if(get_group_map_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) {
627                                 sid_peek_rid(&map.sid, &group_rid);
628                         } 
629                         else {
630                                 group_rid=pdb_gid_to_group_rid(gid);
631                         }
632                 }
633         }
634
635         if (!get_single_attribute(ldap_struct, entry, "pwdLastSet", temp)) {
636                 /* leave as default */
637         } else {
638                 pass_last_set_time = (time_t) atol(temp);
639                 pdb_set_pass_last_set_time(sampass, pass_last_set_time);
640         }
641
642         if (!get_single_attribute(ldap_struct, entry, "logonTime", temp)) {
643                 /* leave as default */
644         } else {
645                 logon_time = (time_t) atol(temp);
646                 pdb_set_logon_time(sampass, logon_time, True);
647         }
648
649         if (!get_single_attribute(ldap_struct, entry, "logoffTime", temp)) {
650                 /* leave as default */
651         } else {
652                 logoff_time = (time_t) atol(temp);
653                 pdb_set_logoff_time(sampass, logoff_time, True);
654         }
655
656         if (!get_single_attribute(ldap_struct, entry, "kickoffTime", temp)) {
657                 /* leave as default */
658         } else {
659                 kickoff_time = (time_t) atol(temp);
660                 pdb_set_kickoff_time(sampass, kickoff_time, True);
661         }
662
663         if (!get_single_attribute(ldap_struct, entry, "pwdCanChange", temp)) {
664                 /* leave as default */
665         } else {
666                 pass_can_change_time = (time_t) atol(temp);
667                 pdb_set_pass_can_change_time(sampass, pass_can_change_time, True);
668         }
669
670         if (!get_single_attribute(ldap_struct, entry, "pwdMustChange", temp)) {
671                 /* leave as default */
672         } else {
673                 pass_must_change_time = (time_t) atol(temp);
674                 pdb_set_pass_must_change_time(sampass, pass_must_change_time, True);
675         }
676
677         /* recommend that 'gecos' and 'displayName' should refer to the same
678          * attribute OID.  userFullName depreciated, only used by Samba
679          * primary rules of LDAP: don't make a new attribute when one is already defined
680          * that fits your needs; using cn then displayName rather than 'userFullName'
681          */
682
683         if (!get_single_attribute(ldap_struct, entry, "cn", fullname)) {
684                 if (!get_single_attribute(ldap_struct, entry, "displayName", fullname)) {
685                         /* leave as default */
686                 } else {
687                         pdb_set_fullname(sampass, fullname);
688                 }
689         } else {
690                 pdb_set_fullname(sampass, fullname);
691         }
692
693         if (!get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive)) {
694                 pdb_set_dir_drive(sampass, standard_sub_specified(sampass->mem_ctx, 
695                                                                   lp_logon_path(),
696                                                                   username, domain, 
697                                                                   uid, gid),
698                                   False);
699         } else {
700                 pdb_set_dir_drive(sampass, dir_drive, True);
701         }
702
703         if (!get_single_attribute(ldap_struct, entry, "smbHome", homedir)) {
704                 pdb_set_dir_drive(sampass, standard_sub_specified(sampass->mem_ctx, 
705                                                                   lp_logon_home(),
706                                                                   username, domain, 
707                                                                   uid, gid), 
708                                   False);
709         } else {
710                 pdb_set_homedir(sampass, homedir, True);
711         }
712
713         if (!get_single_attribute(ldap_struct, entry, "scriptPath", logon_script)) {
714                 pdb_set_logon_script(sampass, standard_sub_specified(sampass->mem_ctx, 
715                                                                      lp_logon_script(),
716                                                                      username, domain, 
717                                                                      uid, gid), 
718                                      False);
719         } else {
720                 pdb_set_logon_script(sampass, logon_script, True);
721         }
722
723         if (!get_single_attribute(ldap_struct, entry, "profilePath", profile_path)) {
724                 pdb_set_profile_path(sampass, standard_sub_specified(sampass->mem_ctx, 
725                                                                      lp_logon_path(),
726                                                                      username, domain, 
727                                                                      uid, gid), 
728                                      False);
729         } else {
730                 pdb_set_profile_path(sampass, profile_path, True);
731         }
732
733         if (!get_single_attribute(ldap_struct, entry, "description", acct_desc)) {
734                 /* leave as default */
735         } else {
736                 pdb_set_acct_desc(sampass, acct_desc);
737         }
738
739         if (!get_single_attribute(ldap_struct, entry, "userWorkstations", workstations)) {
740                 /* leave as default */;
741         } else {
742                 pdb_set_workstations(sampass, workstations);
743         }
744
745         /* FIXME: hours stuff should be cleaner */
746         
747         logon_divs = 168;
748         hours_len = 21;
749         memset(hours, 0xff, hours_len);
750
751         if (!get_single_attribute (ldap_struct, entry, "lmPassword", temp)) {
752                 /* leave as default */
753         } else {
754                 pdb_gethexpwd(temp, smblmpwd);
755                 memset((char *)temp, '\0', sizeof(temp));
756                 if (!pdb_set_lanman_passwd(sampass, smblmpwd))
757                         return False;
758         }
759
760         if (!get_single_attribute (ldap_struct, entry, "ntPassword", temp)) {
761                 /* leave as default */
762         } else {
763                 pdb_gethexpwd(temp, smbntpwd);
764                 memset((char *)temp, '\0', sizeof(temp));
765                 if (!pdb_set_nt_passwd(sampass, smbntpwd))
766                         return False;
767         }
768
769         if (!get_single_attribute (ldap_struct, entry, "acctFlags", temp)) {
770                 acct_ctrl |= ACB_NORMAL;
771         } else {
772                 acct_ctrl = pdb_decode_acct_ctrl(temp);
773
774                 if (acct_ctrl == 0)
775                         acct_ctrl |= ACB_NORMAL;
776
777                 pdb_set_acct_ctrl(sampass, acct_ctrl);
778         }
779
780         pdb_set_hours_len(sampass, hours_len);
781         pdb_set_logon_divs(sampass, logon_divs);
782
783         pdb_set_user_rid(sampass, user_rid);
784         pdb_set_group_rid(sampass, group_rid);
785
786         pdb_set_username(sampass, username);
787
788         pdb_set_domain(sampass, domain);
789         pdb_set_nt_username(sampass, nt_username);
790
791         pdb_set_munged_dial(sampass, munged_dial);
792         
793         /* pdb_set_unknown_3(sampass, unknown3); */
794         /* pdb_set_unknown_5(sampass, unknown5); */
795         /* pdb_set_unknown_6(sampass, unknown6); */
796
797         pdb_set_hours(sampass, hours);
798
799         return True;
800 }
801
802 /**********************************************************************
803 Initialize SAM_ACCOUNT from an LDAP query
804 (Based on init_buffer_from_sam in pdb_tdb.c)
805 *********************************************************************/
806 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, 
807                                 LDAPMod *** mods, int ldap_op, 
808                                 const SAM_ACCOUNT * sampass)
809 {
810         pstring temp;
811         uint32 rid;
812
813         if (mods == NULL || sampass == NULL) {
814                 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
815                 return False;
816         }
817
818         *mods = NULL;
819
820         /* 
821          * took out adding "objectclass: sambaAccount"
822          * do this on a per-mod basis
823          */
824
825         make_a_mod(mods, ldap_op, "uid", pdb_get_username(sampass));
826         DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
827
828         if ( pdb_get_user_rid(sampass) ) {
829                 rid = pdb_get_user_rid(sampass);
830         } else if (IS_SAM_SET(sampass, FLAG_SAM_UID)) {
831                 rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass));
832         } else if (ldap_state->permit_non_unix_accounts) {
833                 rid = ldapsam_get_next_available_nua_rid(ldap_state);
834                 if (rid == 0) {
835                         DEBUG(0, ("NO user RID specified on account %s, and findining next available NUA RID failed, cannot store!\n", pdb_get_username(sampass)));
836                         return False;
837                 }
838         } else {
839                 DEBUG(0, ("NO user RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
840                 return False;
841         }
842
843         slprintf(temp, sizeof(temp) - 1, "%i", rid);
844         make_a_mod(mods, ldap_op, "rid", temp);
845
846         if ( pdb_get_group_rid(sampass) ) {
847                 rid = pdb_get_group_rid(sampass);
848         } else if (IS_SAM_SET(sampass, FLAG_SAM_GID)) {
849                 rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
850         } else if (ldap_state->permit_non_unix_accounts) {
851                 rid = DOMAIN_GROUP_RID_USERS;
852         } else {
853                 DEBUG(0, ("NO group RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
854                 return False;
855         }
856
857         slprintf(temp, sizeof(temp) - 1, "%i", rid);
858         make_a_mod(mods, ldap_op, "primaryGroupID", temp);
859
860         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
861         make_a_mod(mods, ldap_op, "pwdLastSet", temp);
862
863         /* displayName, cn, and gecos should all be the same
864            *  most easily accomplished by giving them the same OID
865            *  gecos isn't set here b/c it should be handled by the 
866            *  add-user script
867          */
868
869         make_a_mod(mods, ldap_op, "displayName", pdb_get_fullname(sampass));
870         make_a_mod(mods, ldap_op, "cn", pdb_get_fullname(sampass));
871         make_a_mod(mods, ldap_op, "description", pdb_get_acct_desc(sampass));
872         make_a_mod(mods, ldap_op, "userWorkstations", pdb_get_workstations(sampass));
873
874         /*
875          * Only updates fields which have been set (not defaults from smb.conf)
876          */
877
878         if (IS_SAM_SET(sampass, FLAG_SAM_SMBHOME))
879                 make_a_mod(mods, ldap_op, "smbHome", pdb_get_homedir(sampass));
880                 
881         if (IS_SAM_SET(sampass, FLAG_SAM_DRIVE))
882                 make_a_mod(mods, ldap_op, "homeDrive", pdb_get_dirdrive(sampass));
883         
884         if (IS_SAM_SET(sampass, FLAG_SAM_LOGONSCRIPT))
885                 make_a_mod(mods, ldap_op, "scriptPath", pdb_get_logon_script(sampass));
886
887         if (IS_SAM_SET(sampass, FLAG_SAM_PROFILE))
888                 make_a_mod(mods, ldap_op, "profilePath", pdb_get_profile_path(sampass));
889
890         if (IS_SAM_SET(sampass, FLAG_SAM_LOGONTIME)) {
891                 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
892                 make_a_mod(mods, ldap_op, "logonTime", temp);
893         }
894
895         if (IS_SAM_SET(sampass, FLAG_SAM_LOGOFFTIME)) {
896                 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
897                 make_a_mod(mods, ldap_op, "logoffTime", temp);
898         }
899
900         if (IS_SAM_SET(sampass, FLAG_SAM_KICKOFFTIME)) {
901                 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
902                 make_a_mod(mods, ldap_op, "kickoffTime", temp);
903         }
904
905         if (IS_SAM_SET(sampass, FLAG_SAM_CANCHANGETIME)) {
906                 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
907                 make_a_mod(mods, ldap_op, "pwdCanChange", temp);
908         }
909
910         if (IS_SAM_SET(sampass, FLAG_SAM_MUSTCHANGETIME)) {
911                 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
912                 make_a_mod(mods, ldap_op, "pwdMustChange", temp);
913         }
914
915         /* FIXME: Hours stuff goes in LDAP  */
916         pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass));
917         make_a_mod (mods, ldap_op, "lmPassword", temp);
918         
919         pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
920         make_a_mod (mods, ldap_op, "ntPassword", temp);
921         
922         make_a_mod (mods, ldap_op, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
923                 NEW_PW_FORMAT_SPACE_PADDED_LEN));
924
925         return True;
926 }
927
928
929 /**********************************************************************
930 Connect to LDAP server and find the next available RID.
931 *********************************************************************/
932 static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid, LDAP *ldap_struct) 
933 {
934         LDAPMessage *result;
935         uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
936         if (top_rid == 0) {
937                 return 0;
938         }
939         
940         if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) {
941                 return 0;
942         }
943
944         if (ldapsam_search_one_user_by_rid(ldap_state, ldap_struct, final_rid, &result) != LDAP_SUCCESS) {
945                 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
946                 final_rid = 0;
947                 ldap_msgfree(result);
948         }
949
950         if (ldap_count_entries(ldap_struct, result) != 0)
951         {
952                 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
953                 final_rid = 0;
954                 ldap_msgfree(result);
955         }
956
957         DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
958         return final_rid;
959 }
960
961 /**********************************************************************
962 Extract the RID from an LDAP entry
963 *********************************************************************/
964 static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, LDAP *ldap_struct) {
965         uint32 rid;
966         SAM_ACCOUNT *user = NULL;
967         if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
968                 return 0;
969         }
970
971         if (init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
972                 rid = pdb_get_user_rid(user);
973         } else {
974                 rid =0;
975         }
976         pdb_free_sam(&user);
977         if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) {
978                 return rid;
979         }
980         return 0;
981 }
982
983
984 /**********************************************************************
985 Connect to LDAP server and find the next available RID.
986 *********************************************************************/
987 static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state, LDAP *ldap_struct)
988 {
989         int rc;
990         pstring filter;
991         LDAPMessage *result;
992         LDAPMessage *entry;
993         char *final_filter = NULL;
994         uint32 top_rid = 0;
995         uint32 count;
996         uint32 rid;
997
998         pstrcpy(filter, lp_ldap_filter());
999         all_string_sub(filter, "%u", "*", sizeof(pstring));
1000
1001 #if 0
1002         asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid);
1003 #else 
1004         final_filter = strdup(filter);
1005 #endif  
1006         DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
1007
1008         rc = ldap_search_s(ldap_struct, lp_ldap_suffix(),
1009                            LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
1010                            &result);
1011
1012         if (rc != LDAP_SUCCESS)
1013         {
1014                 
1015                 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1016                 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1017
1018                 free(final_filter);
1019                 ldap_msgfree(result);
1020                 result = NULL;
1021                 return 0;
1022         }
1023         
1024         count = ldap_count_entries(ldap_struct, result);
1025         DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count));
1026         
1027         if (count == 0) {
1028                 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc)));
1029                 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1030                 free(final_filter);
1031                 ldap_msgfree(result);
1032                 result = NULL;
1033                 return ldap_state->low_nua_rid;
1034         }
1035         
1036         free(final_filter);
1037         entry = ldap_first_entry(ldap_struct,result);
1038
1039         top_rid = entry_to_user_rid(ldap_state, entry, ldap_struct);
1040
1041         while ((entry = ldap_next_entry(ldap_struct, entry))) {
1042
1043                 rid = entry_to_user_rid(ldap_state, entry, ldap_struct);
1044                 if (rid > top_rid) {
1045                         top_rid = rid;
1046                 }
1047         }
1048
1049         ldap_msgfree(result);
1050         return top_rid;
1051 }
1052
1053 /**********************************************************************
1054 Connect to LDAP server and find the next available RID.
1055 *********************************************************************/
1056 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) {
1057         LDAP *ldap_struct;
1058         uint32 next_nua_rid;
1059         uint32 top_nua_rid;
1060
1061         if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1062         {
1063                 return 0;
1064         }
1065         if (!ldapsam_connect_system(ldap_state, ldap_struct))
1066         {
1067                 ldap_unbind(ldap_struct);
1068                 return 0;
1069         }
1070         
1071         top_nua_rid = search_top_nua_rid(ldap_state, ldap_struct);
1072
1073         next_nua_rid = check_nua_rid_is_avail(ldap_state, 
1074                                               top_nua_rid, ldap_struct);
1075         
1076         ldap_unbind(ldap_struct);
1077         return next_nua_rid;
1078 }
1079
1080 /**********************************************************************
1081 Connect to LDAP server for password enumeration
1082 *********************************************************************/
1083 static BOOL ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
1084 {
1085         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1086         int rc;
1087         pstring filter;
1088
1089         if (!ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))
1090         {
1091                 return False;
1092         }
1093         if (!ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))
1094         {
1095                 ldap_unbind(ldap_state->ldap_struct);
1096                 return False;
1097         }
1098
1099         pstrcpy(filter, lp_ldap_filter());
1100         all_string_sub(filter, "%u", "*", sizeof(pstring));
1101
1102         rc = ldap_search_s(ldap_state->ldap_struct, lp_ldap_suffix(),
1103                            LDAP_SCOPE_SUBTREE, filter, attr, 0,
1104                            &ldap_state->result);
1105
1106         if (rc != LDAP_SUCCESS)
1107         {
1108                 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1109                 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1110                 ldap_msgfree(ldap_state->result);
1111                 ldap_unbind(ldap_state->ldap_struct);
1112                 ldap_state->ldap_struct = NULL;
1113                 ldap_state->result = NULL;
1114                 return False;
1115         }
1116
1117         DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1118                 ldap_count_entries(ldap_state->ldap_struct,
1119                 ldap_state->result)));
1120
1121         ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1122                                  ldap_state->result);
1123         ldap_state->index = 0;
1124
1125         return True;
1126 }
1127
1128 /**********************************************************************
1129 End enumeration of the LDAP password list 
1130 *********************************************************************/
1131 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1132 {
1133         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1134         if (ldap_state->ldap_struct && ldap_state->result)
1135         {
1136                 ldap_msgfree(ldap_state->result);
1137                 ldap_unbind(ldap_state->ldap_struct);
1138                 ldap_state->ldap_struct = NULL;
1139                 ldap_state->result = NULL;
1140         }
1141 }
1142
1143 /**********************************************************************
1144 Get the next entry in the LDAP password database 
1145 *********************************************************************/
1146 static BOOL ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * user)
1147 {
1148         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1149         BOOL ret = False;
1150
1151         while (!ret) {
1152                 if (!ldap_state->entry)
1153                         return False;
1154                 
1155                 ldap_state->index++;
1156                 ret = init_sam_from_ldap(ldap_state, user, ldap_state->ldap_struct,
1157                                          ldap_state->entry);
1158                 
1159                 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
1160                                             ldap_state->entry);
1161                 
1162         }
1163
1164         return True;
1165 }
1166
1167 /**********************************************************************
1168 Get SAM_ACCOUNT entry from LDAP by username 
1169 *********************************************************************/
1170 static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const char *sname)
1171 {
1172         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1173         LDAP *ldap_struct;
1174         LDAPMessage *result;
1175         LDAPMessage *entry;
1176
1177         if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1178                 return False;
1179         if (!ldapsam_connect_system(ldap_state, ldap_struct))
1180         {
1181                 ldap_unbind(ldap_struct);
1182                 return False;
1183         }
1184         if (ldapsam_search_one_user_by_name(ldap_state, ldap_struct, sname, &result) != LDAP_SUCCESS)
1185         {
1186                 ldap_unbind(ldap_struct);
1187                 return False;
1188         }
1189         if (ldap_count_entries(ldap_struct, result) < 1)
1190         {
1191                 DEBUG(4,
1192                       ("We don't find this user [%s] count=%d\n", sname,
1193                        ldap_count_entries(ldap_struct, result)));
1194                 ldap_unbind(ldap_struct);
1195                 return False;
1196         }
1197         entry = ldap_first_entry(ldap_struct, result);
1198         if (entry)
1199         {
1200                 if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
1201                         DEBUG(0,("ldapsam_getsampwnam: init_sam_from_ldap failed!\n"));
1202                         ldap_msgfree(result);
1203                         ldap_unbind(ldap_struct);
1204                         return False;
1205                 }
1206                 ldap_msgfree(result);
1207                 ldap_unbind(ldap_struct);
1208                 return True;
1209         }
1210         else
1211         {
1212                 ldap_msgfree(result);
1213                 ldap_unbind(ldap_struct);
1214                 return False;
1215         }
1216 }
1217
1218 /**********************************************************************
1219 Get SAM_ACCOUNT entry from LDAP by rid 
1220 *********************************************************************/
1221 static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, uint32 rid)
1222 {
1223         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1224         LDAP *ldap_struct;
1225         LDAPMessage *result;
1226         LDAPMessage *entry;
1227
1228         if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1229                 return False;
1230
1231         if (!ldapsam_connect_system(ldap_state, ldap_struct))
1232         {
1233                 ldap_unbind(ldap_struct);
1234                 return False;
1235         }
1236         if (ldapsam_search_one_user_by_rid(ldap_state, ldap_struct, rid, &result) !=
1237             LDAP_SUCCESS)
1238         {
1239                 ldap_unbind(ldap_struct);
1240                 return False;
1241         }
1242
1243         if (ldap_count_entries(ldap_struct, result) < 1)
1244         {
1245                 DEBUG(0,
1246                       ("We don't find this rid [%i] count=%d\n", rid,
1247                        ldap_count_entries(ldap_struct, result)));
1248                 ldap_unbind(ldap_struct);
1249                 return False;
1250         }
1251
1252         entry = ldap_first_entry(ldap_struct, result);
1253         if (entry)
1254         {
1255                 if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
1256                         DEBUG(0,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1257                         ldap_msgfree(result);
1258                         ldap_unbind(ldap_struct);
1259                         return False;
1260                 }
1261                 ldap_msgfree(result);
1262                 ldap_unbind(ldap_struct);
1263                 return True;
1264         }
1265         else
1266         {
1267                 ldap_msgfree(result);
1268                 ldap_unbind(ldap_struct);
1269                 return False;
1270         }
1271 }
1272
1273 /**********************************************************************
1274 Delete entry from LDAP for username 
1275 *********************************************************************/
1276 static BOOL ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1277 {
1278         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1279         const char *sname;
1280         int rc;
1281         char *dn;
1282         LDAP *ldap_struct;
1283         LDAPMessage *entry;
1284         LDAPMessage *result;
1285
1286         if (!sam_acct) {
1287                 DEBUG(0, ("sam_acct was NULL!\n"));
1288                 return False;
1289         }
1290
1291         sname = pdb_get_username(sam_acct);
1292
1293         if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1294                 return False;
1295
1296         DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1297         
1298         if (!ldapsam_connect_system(ldap_state, ldap_struct)) {
1299                 ldap_unbind (ldap_struct);
1300                 DEBUG(0, ("Failed to delete user %s from LDAP.\n", sname));
1301                 return False;
1302         }
1303
1304         rc = ldapsam_search_one_user_by_name(ldap_state, ldap_struct, sname, &result);
1305         if (ldap_count_entries (ldap_struct, result) == 0) {
1306                 DEBUG (0, ("User doesn't exit!\n"));
1307                 ldap_msgfree (result);
1308                 ldap_unbind (ldap_struct);
1309                 return False;
1310         }
1311
1312         entry = ldap_first_entry (ldap_struct, result);
1313         dn = ldap_get_dn (ldap_struct, entry);
1314
1315         rc = ldap_delete_s (ldap_struct, dn);
1316
1317         ldap_memfree (dn);
1318         if (rc != LDAP_SUCCESS) {
1319                 char *ld_error;
1320                 ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1321                 DEBUG (0,("failed to delete user with uid = %s with: %s\n\t%s\n",
1322                         sname, ldap_err2string (rc), ld_error));
1323                 free (ld_error);
1324                 ldap_unbind (ldap_struct);
1325                 return False;
1326         }
1327
1328         DEBUG (2,("successfully deleted uid = %s from the LDAP database\n", sname));
1329         ldap_unbind (ldap_struct);
1330         return True;
1331 }
1332
1333 /**********************************************************************
1334 Update SAM_ACCOUNT 
1335 *********************************************************************/
1336 static BOOL ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1337 {
1338         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1339         int rc;
1340         char *dn;
1341         LDAP *ldap_struct;
1342         LDAPMessage *result;
1343         LDAPMessage *entry;
1344         LDAPMod **mods;
1345
1346         if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */
1347                 return False;
1348
1349         if (!ldapsam_connect_system(ldap_state, ldap_struct))   /* connect as system account */
1350         {
1351                 ldap_unbind(ldap_struct);
1352                 return False;
1353         }
1354
1355         rc = ldapsam_search_one_user_by_name(ldap_state, ldap_struct,
1356                                              pdb_get_username(newpwd), &result);
1357
1358         if (ldap_count_entries(ldap_struct, result) == 0)
1359         {
1360                 DEBUG(0, ("No user to modify!\n"));
1361                 ldap_msgfree(result);
1362                 ldap_unbind(ldap_struct);
1363                 return False;
1364         }
1365
1366         if (!init_ldap_from_sam(ldap_state, &mods, LDAP_MOD_REPLACE, newpwd)) {
1367                 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1368                 ldap_msgfree(result);
1369                 ldap_unbind(ldap_struct);
1370                 return False;
1371         }
1372
1373         entry = ldap_first_entry(ldap_struct, result);
1374         dn = ldap_get_dn(ldap_struct, entry);
1375
1376         rc = ldap_modify_s(ldap_struct, dn, mods);
1377
1378         if (rc != LDAP_SUCCESS)
1379         {
1380                 char *ld_error;
1381                 ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING,
1382                                 &ld_error);
1383                 DEBUG(0,
1384                       ("failed to modify user with uid = %s with: %s\n\t%s\n",
1385                        pdb_get_username(newpwd), ldap_err2string(rc),
1386                        ld_error));
1387                 free(ld_error);
1388                 ldap_unbind(ldap_struct);
1389                 return False;
1390         }
1391
1392         DEBUG(2,
1393               ("successfully modified uid = %s in the LDAP database\n",
1394                pdb_get_username(newpwd)));
1395         ldap_mods_free(mods, 1);
1396         ldap_unbind(ldap_struct);
1397         return True;
1398 }
1399
1400 /**********************************************************************
1401 Add SAM_ACCOUNT to LDAP 
1402 *********************************************************************/
1403 static BOOL ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1404 {
1405         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1406         int rc;
1407         pstring filter;
1408         LDAP *ldap_struct = NULL;
1409         LDAPMessage *result = NULL;
1410         pstring dn;
1411         LDAPMod **mods = NULL;
1412         int             ldap_op;
1413         uint32          num_result;
1414
1415         const char *username = pdb_get_username(newpwd);
1416         if (!username || !*username) {
1417                 DEBUG(0, ("Cannot add user without a username!\n"));
1418                 return False;
1419         }
1420
1421         if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */
1422         {
1423                 return False;
1424         }
1425
1426         if (!ldapsam_connect_system(ldap_state, ldap_struct))   /* connect as system account */
1427         {
1428                 ldap_unbind(ldap_struct);
1429                 return False;
1430         }
1431
1432         rc = ldapsam_search_one_user_by_name (ldap_state, ldap_struct, username, &result);
1433
1434         if (ldap_count_entries(ldap_struct, result) != 0)
1435         {
1436                 DEBUG(0,("User already in the base, with samba properties\n"));
1437                 ldap_msgfree(result);
1438                 ldap_unbind(ldap_struct);
1439                 return False;
1440         }
1441         ldap_msgfree(result);
1442
1443         slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
1444         rc = ldapsam_search_one_user(ldap_state, ldap_struct, filter, &result);
1445         num_result = ldap_count_entries(ldap_struct, result);
1446         
1447         if (num_result > 1) {
1448                 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1449                 ldap_msgfree(result);
1450                 return False;
1451         }
1452         
1453         /* Check if we need to update an existing entry */
1454         if (num_result == 1) {
1455                 char *tmp;
1456                 LDAPMessage *entry;
1457                 
1458                 DEBUG(3,("User exists without samba properties: adding them\n"));
1459                 ldap_op = LDAP_MOD_REPLACE;
1460                 entry = ldap_first_entry (ldap_struct, result);
1461                 tmp = ldap_get_dn (ldap_struct, entry);
1462                 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1463                 ldap_memfree (tmp);
1464         }
1465         else {
1466                 /* Check if we need to add an entry */
1467                 DEBUG(3,("Adding new user\n"));
1468                 ldap_op = LDAP_MOD_ADD;
1469                 if (username[strlen(username)-1] == '$') {
1470                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
1471                 } else {
1472                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
1473                 }
1474         }
1475
1476         ldap_msgfree(result);
1477
1478         if (!init_ldap_from_sam(ldap_state, &mods, ldap_op, newpwd)) {
1479                 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1480                 ldap_mods_free(mods, 1);
1481                 ldap_unbind(ldap_struct);
1482                 return False;           
1483         }
1484         make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
1485
1486         if (ldap_op == LDAP_MOD_REPLACE) {
1487                 rc = ldap_modify_s(ldap_struct, dn, mods);
1488         }
1489         else {
1490                 rc = ldap_add_s(ldap_struct, dn, mods);
1491         }
1492
1493         if (rc != LDAP_SUCCESS)
1494         {
1495                 char *ld_error;
1496
1497                 ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1498                 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s) with: %s\n\t%s\n",
1499                         pdb_get_username(newpwd), dn, ldap_err2string (rc), ld_error));
1500                 free(ld_error);
1501                 ldap_mods_free(mods, 1);
1502                 ldap_unbind(ldap_struct);
1503                 return False;
1504         }
1505         
1506         DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
1507         ldap_mods_free(mods, 1);
1508         ldap_unbind(ldap_struct);
1509         return True;
1510 }
1511
1512 static void free_private_data(void **vp) 
1513 {
1514         struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
1515
1516         if ((*ldap_state)->ldap_struct) {
1517                 ldap_unbind((*ldap_state)->ldap_struct);
1518         }
1519
1520         *ldap_state = NULL;
1521
1522         /* No need to free any further, as it is talloc()ed */
1523 }
1524
1525 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1526 {
1527         NTSTATUS nt_status;
1528         struct ldapsam_privates *ldap_state;
1529
1530         if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
1531                 return nt_status;
1532         }
1533
1534         (*pdb_method)->name = "ldapsam";
1535
1536         (*pdb_method)->setsampwent = ldapsam_setsampwent;
1537         (*pdb_method)->endsampwent = ldapsam_endsampwent;
1538         (*pdb_method)->getsampwent = ldapsam_getsampwent;
1539         (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
1540         (*pdb_method)->getsampwrid = ldapsam_getsampwrid;
1541         (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
1542         (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
1543         (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
1544
1545         /* TODO: Setup private data and free */
1546
1547         ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
1548
1549         if (!ldap_state) {
1550                 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1551                 return NT_STATUS_NO_MEMORY;
1552         }
1553
1554         if (location) {
1555                 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
1556         } else {
1557                 ldap_state->uri = "ldap://localhost";
1558         }
1559
1560         (*pdb_method)->private_data = ldap_state;
1561
1562         (*pdb_method)->free_private_data = free_private_data;
1563
1564         return NT_STATUS_OK;
1565 }
1566
1567 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1568 {
1569         NTSTATUS nt_status;
1570         struct ldapsam_privates *ldap_state;
1571         uint32 low_nua_uid, high_nua_uid;
1572
1573         if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
1574                 return nt_status;
1575         }
1576
1577         (*pdb_method)->name = "ldapsam_nua";
1578
1579         ldap_state = (*pdb_method)->private_data;
1580         
1581         ldap_state->permit_non_unix_accounts = True;
1582
1583         if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
1584                 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
1585                 return NT_STATUS_UNSUCCESSFUL;
1586         }
1587
1588         ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
1589
1590         ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
1591
1592         return NT_STATUS_OK;
1593 }
1594
1595
1596 #else
1597
1598 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1599 {
1600         DEBUG(0, ("ldap not detected at configure time, ldapsam not availalble!\n"));
1601         return NT_STATUS_UNSUCCESSFUL;
1602 }
1603
1604 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1605 {
1606         DEBUG(0, ("ldap not dectected at configure time, ldapsam_nua not available!\n"));
1607         return NT_STATUS_UNSUCCESSFUL;
1608 }
1609
1610
1611 #endif