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