r6225: get rid of warnings from my compiler about nested externs
[samba.git] / source3 / passdb / pdb_ldap.c
1 /* 
2    Unix SMB/CIFS implementation.
3    LDAP protocol helper functions for SAMBA
4    Copyright (C) Jean François Micouleau        1998
5    Copyright (C) Gerald Carter                  2001-2003
6    Copyright (C) Shahms King                    2001
7    Copyright (C) Andrew Bartlett                2002-2003
8    Copyright (C) Stefan (metze) Metzmacher      2002-2003
9     
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23    
24 */
25
26 /* TODO:
27 *  persistent connections: if using NSS LDAP, many connections are made
28 *      however, using only one within Samba would be nice
29 *  
30 *  Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
31 *
32 *  Other LDAP based login attributes: accountExpires, etc.
33 *  (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
34 *  structures don't have fields for some of these attributes)
35 *
36 *  SSL is done, but can't get the certificate based authentication to work
37 *  against on my test platform (Linux 2.4, OpenLDAP 2.x)
38 */
39
40 /* NOTE: this will NOT work against an Active Directory server
41 *  due to the fact that the two password fields cannot be retrieved
42 *  from a server; recommend using security = domain in this situation
43 *  and/or winbind
44 */
45
46 #include "includes.h"
47
48 extern DOM_SID global_sid_NULL;
49
50 #undef DBGC_CLASS
51 #define DBGC_CLASS DBGC_PASSDB
52
53 #include <lber.h>
54 #include <ldap.h>
55
56 /*
57  * Work around versions of the LDAP client libs that don't have the OIDs
58  * defined, or have them defined under the old name.  
59  * This functionality is really a factor of the server, not the client 
60  *
61  */
62
63 #if defined(LDAP_EXOP_X_MODIFY_PASSWD) && !defined(LDAP_EXOP_MODIFY_PASSWD)
64 #define LDAP_EXOP_MODIFY_PASSWD LDAP_EXOP_X_MODIFY_PASSWD
65 #elif !defined(LDAP_EXOP_MODIFY_PASSWD)
66 #define LDAP_EXOP_MODIFY_PASSWD "1.3.6.1.4.1.4203.1.11.1"
67 #endif
68
69 #if defined(LDAP_EXOP_X_MODIFY_PASSWD_ID) && !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
70 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID LDAP_EXOP_X_MODIFY_PASSWD_ID
71 #elif !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
72 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID        ((ber_tag_t) 0x80U)
73 #endif
74
75 #if defined(LDAP_EXOP_X_MODIFY_PASSWD_NEW) && !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
76 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW LDAP_EXOP_X_MODIFY_PASSWD_NEW
77 #elif !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
78 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW       ((ber_tag_t) 0x82U)
79 #endif
80
81
82 #ifndef SAM_ACCOUNT
83 #define SAM_ACCOUNT struct sam_passwd
84 #endif
85
86 #include "smbldap.h"
87
88 /**********************************************************************
89  Free a LDAPMessage (one is stored on the SAM_ACCOUNT).
90  **********************************************************************/
91  
92 void private_data_free_fn(void **result) 
93 {
94         ldap_msgfree(*result);
95         *result = NULL;
96 }
97
98 /**********************************************************************
99  Get the attribute name given a user schame version.
100  **********************************************************************/
101  
102 static const char* get_userattr_key2string( int schema_ver, int key )
103 {
104         switch ( schema_ver ) {
105                 case SCHEMAVER_SAMBAACCOUNT:
106                         return get_attr_key2string( attrib_map_v22, key );
107                         
108                 case SCHEMAVER_SAMBASAMACCOUNT:
109                         return get_attr_key2string( attrib_map_v30, key );
110                         
111                 default:
112                         DEBUG(0,("get_userattr_key2string: unknown schema version specified\n"));
113                         break;
114         }
115         return NULL;
116 }
117
118 /**********************************************************************
119  Return the list of attribute names given a user schema version.
120 **********************************************************************/
121
122 const char** get_userattr_list( int schema_ver )
123 {
124         switch ( schema_ver ) {
125                 case SCHEMAVER_SAMBAACCOUNT:
126                         return get_attr_list( attrib_map_v22 );
127                         
128                 case SCHEMAVER_SAMBASAMACCOUNT:
129                         return get_attr_list( attrib_map_v30 );
130                 default:
131                         DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
132                         break;
133         }
134         
135         return NULL;
136 }
137
138 /**************************************************************************
139  Return the list of attribute names to delete given a user schema version.
140 **************************************************************************/
141
142 static const char** get_userattr_delete_list( int schema_ver )
143 {
144         switch ( schema_ver ) {
145                 case SCHEMAVER_SAMBAACCOUNT:
146                         return get_attr_list( attrib_map_to_delete_v22 );
147                         
148                 case SCHEMAVER_SAMBASAMACCOUNT:
149                         return get_attr_list( attrib_map_to_delete_v30 );
150                 default:
151                         DEBUG(0,("get_userattr_delete_list: unknown schema version specified!\n"));
152                         break;
153         }
154         
155         return NULL;
156 }
157
158
159 /*******************************************************************
160  Generate the LDAP search filter for the objectclass based on the 
161  version of the schema we are using.
162 ******************************************************************/
163
164 static const char* get_objclass_filter( int schema_ver )
165 {
166         static fstring objclass_filter;
167         
168         switch( schema_ver ) {
169                 case SCHEMAVER_SAMBAACCOUNT:
170                         fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT );
171                         break;
172                 case SCHEMAVER_SAMBASAMACCOUNT:
173                         fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT );
174                         break;
175                 default:
176                         DEBUG(0,("get_objclass_filter: Invalid schema version specified!\n"));
177                         break;
178         }
179         
180         return objclass_filter; 
181 }
182
183 /*******************************************************************
184  Run the search by name.
185 ******************************************************************/
186
187 int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state, 
188                                           const char *user,
189                                           LDAPMessage ** result,
190                                           const char **attr)
191 {
192         pstring filter;
193         char *escape_user = escape_ldap_string_alloc(user);
194
195         if (!escape_user) {
196                 return LDAP_NO_MEMORY;
197         }
198
199         /*
200          * in the filter expression, replace %u with the real name
201          * so in ldap filter, %u MUST exist :-)
202          */
203         pstr_sprintf(filter, "(&%s%s)", lp_ldap_filter(), 
204                 get_objclass_filter(ldap_state->schema_ver));
205
206         /* 
207          * have to use this here because $ is filtered out
208            * in pstring_sub
209          */
210         
211
212         all_string_sub(filter, "%u", escape_user, sizeof(pstring));
213         SAFE_FREE(escape_user);
214
215         return smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result);
216 }
217
218 /*******************************************************************
219  Run the search by rid.
220 ******************************************************************/
221
222 static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, 
223                                          uint32 rid, LDAPMessage ** result, 
224                                          const char **attr)
225 {
226         pstring filter;
227         int rc;
228
229         pstr_sprintf(filter, "(&(rid=%i)%s)", rid, 
230                 get_objclass_filter(ldap_state->schema_ver));
231         
232         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result);
233         
234         return rc;
235 }
236
237 /*******************************************************************
238  Run the search by SID.
239 ******************************************************************/
240
241 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, 
242                                          const DOM_SID *sid, LDAPMessage ** result, 
243                                          const char **attr)
244 {
245         pstring filter;
246         int rc;
247         fstring sid_string;
248
249         pstr_sprintf(filter, "(&(%s=%s)%s)", 
250                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
251                 sid_to_string(sid_string, sid), 
252                 get_objclass_filter(ldap_state->schema_ver));
253                 
254         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result);
255         
256         return rc;
257 }
258
259 /*******************************************************************
260  Delete complete object or objectclass and attrs from
261  object found in search_result depending on lp_ldap_delete_dn
262 ******************************************************************/
263
264 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
265                                      LDAPMessage *result,
266                                      const char *objectclass,
267                                      const char **attrs)
268 {
269         int rc;
270         LDAPMessage *entry = NULL;
271         LDAPMod **mods = NULL;
272         char *name, *dn;
273         BerElement *ptr = NULL;
274
275         rc = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
276
277         if (rc != 1) {
278                 DEBUG(0, ("ldapsam_delete_entry: Entry must exist exactly once!\n"));
279                 return NT_STATUS_UNSUCCESSFUL;
280         }
281
282         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
283         dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
284         if (!dn) {
285                 return NT_STATUS_UNSUCCESSFUL;
286         }
287
288         if (lp_ldap_delete_dn()) {
289                 NTSTATUS ret = NT_STATUS_OK;
290                 rc = smbldap_delete(ldap_state->smbldap_state, dn);
291
292                 if (rc != LDAP_SUCCESS) {
293                         DEBUG(0, ("ldapsam_delete_entry: Could not delete object %s\n", dn));
294                         ret = NT_STATUS_UNSUCCESSFUL;
295                 }
296                 SAFE_FREE(dn);
297                 return ret;
298         }
299
300         /* Ok, delete only the SAM attributes */
301         
302         for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr);
303              name != NULL;
304              name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) {
305                 const char **attrib;
306
307                 /* We are only allowed to delete the attributes that
308                    really exist. */
309
310                 for (attrib = attrs; *attrib != NULL; attrib++) {
311                         /* Don't delete LDAP_ATTR_MOD_TIMESTAMP attribute. */
312                         if (strequal(*attrib, get_userattr_key2string(ldap_state->schema_ver,
313                                                 LDAP_ATTR_MOD_TIMESTAMP))) {
314                                 continue;
315                         }
316                         if (strequal(*attrib, name)) {
317                                 DEBUG(10, ("ldapsam_delete_entry: deleting "
318                                            "attribute %s\n", name));
319                                 smbldap_set_mod(&mods, LDAP_MOD_DELETE, name,
320                                                 NULL);
321                         }
322                 }
323
324                 ldap_memfree(name);
325         }
326         
327         if (ptr != NULL) {
328                 ber_free(ptr, 0);
329         }
330         
331         smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
332
333         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
334         ldap_mods_free(mods, True);
335
336         if (rc != LDAP_SUCCESS) {
337                 char *ld_error = NULL;
338                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
339                                 &ld_error);
340                 
341                 DEBUG(0, ("ldapsam_delete_entry: Could not delete attributes for %s, error: %s (%s)\n",
342                           dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
343                 SAFE_FREE(ld_error);
344                 SAFE_FREE(dn);
345                 return NT_STATUS_UNSUCCESSFUL;
346         }
347
348         SAFE_FREE(dn);
349         return NT_STATUS_OK;
350 }
351                   
352 /* New Interface is being implemented here */
353
354 #if 0   /* JERRY - not uesed anymore */
355
356 /**********************************************************************
357 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
358 *********************************************************************/
359 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, 
360                                 SAM_ACCOUNT * sampass,
361                                 LDAPMessage * entry,
362                                 gid_t *gid)
363 {
364         pstring  homedir;
365         pstring  temp;
366         char **ldap_values;
367         char **values;
368
369         if ((ldap_values = ldap_get_values (ldap_state->smbldap_state->ldap_struct, entry, "objectClass")) == NULL) {
370                 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
371                 return False;
372         }
373
374         for (values=ldap_values;*values;values++) {
375                 if (strequal(*values, LDAP_OBJ_POSIXACCOUNT )) {
376                         break;
377                 }
378         }
379         
380         if (!*values) { /*end of array, no posixAccount */
381                 DEBUG(10, ("user does not have %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
382                 ldap_value_free(ldap_values);
383                 return False;
384         }
385         ldap_value_free(ldap_values);
386
387         if ( !smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
388                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_UNIX_HOME), homedir) ) 
389         {
390                 return False;
391         }
392         
393         if ( !smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
394                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_GIDNUMBER), temp) )
395         {
396                 return False;
397         }
398         
399         *gid = (gid_t)atol(temp);
400
401         pdb_set_unix_homedir(sampass, homedir, PDB_SET);
402         
403         DEBUG(10, ("user has %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
404         
405         return True;
406 }
407
408 #endif
409
410 static time_t ldapsam_get_entry_timestamp(
411         struct ldapsam_privates *ldap_state,
412         LDAPMessage * entry)
413 {
414         pstring temp;   
415         struct tm tm;
416
417         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
418                         get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP),
419                         temp))
420                 return (time_t) 0;
421
422         strptime(temp, "%Y%m%d%H%M%SZ", &tm);
423         tzset();
424         return timegm(&tm);
425 }
426
427 /**********************************************************************
428  Initialize SAM_ACCOUNT from an LDAP query.
429  (Based on init_sam_from_buffer in pdb_tdb.c)
430 *********************************************************************/
431
432 static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state, 
433                                 SAM_ACCOUNT * sampass,
434                                 LDAPMessage * entry)
435 {
436         time_t  logon_time,
437                         logoff_time,
438                         kickoff_time,
439                         pass_last_set_time, 
440                         pass_can_change_time, 
441                         pass_must_change_time,
442                         ldap_entry_time,
443                         bad_password_time;
444         pstring         username, 
445                         domain,
446                         nt_username,
447                         fullname,
448                         homedir,
449                         dir_drive,
450                         logon_script,
451                         profile_path,
452                         acct_desc,
453                         workstations;
454         char            munged_dial[2048];
455         uint32          user_rid; 
456         uint8           smblmpwd[LM_HASH_LEN],
457                         smbntpwd[NT_HASH_LEN];
458         BOOL            use_samba_attrs = True;
459         uint16          acct_ctrl = 0, 
460                         logon_divs;
461         uint16          bad_password_count = 0, 
462                         logon_count = 0;
463         uint32 hours_len;
464         uint8           hours[MAX_HOURS_LEN];
465         pstring temp;
466         LOGIN_CACHE     *cache_entry = NULL;
467         uint32          pwHistLen;
468         pstring         tmpstring;
469
470         /*
471          * do a little initialization
472          */
473         username[0]     = '\0';
474         domain[0]       = '\0';
475         nt_username[0]  = '\0';
476         fullname[0]     = '\0';
477         homedir[0]      = '\0';
478         dir_drive[0]    = '\0';
479         logon_script[0] = '\0';
480         profile_path[0] = '\0';
481         acct_desc[0]    = '\0';
482         munged_dial[0]  = '\0';
483         workstations[0] = '\0';
484          
485
486         if (sampass == NULL || ldap_state == NULL || entry == NULL) {
487                 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
488                 return False;
489         }
490
491         if (ldap_state->smbldap_state->ldap_struct == NULL) {
492                 DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->ldap_struct is NULL!\n"));
493                 return False;
494         }
495         
496         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) {
497                 DEBUG(1, ("init_sam_from_ldap: No uid attribute found for this user!\n"));
498                 return False;
499         }
500
501         DEBUG(2, ("init_sam_from_ldap: Entry found for user: %s\n", username));
502
503         pstrcpy(nt_username, username);
504
505         pstrcpy(domain, ldap_state->domain_name);
506         
507         pdb_set_username(sampass, username, PDB_SET);
508
509         pdb_set_domain(sampass, domain, PDB_DEFAULT);
510         pdb_set_nt_username(sampass, nt_username, PDB_SET);
511
512         /* deal with different attributes between the schema first */
513         
514         if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ) {
515                 if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
516                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp)) {
517                         pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
518                 }
519                 
520                 if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
521                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp)) {
522                         pdb_set_group_sid_from_string(sampass, temp, PDB_SET);                  
523                 } else {
524                         pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
525                 }
526         } else {
527                 if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
528                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp)) {
529                         user_rid = (uint32)atol(temp);
530                         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
531                 }
532                 
533                 if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
534                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp)) {
535                         pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
536                 } else {
537                         uint32 group_rid;
538                         
539                         group_rid = (uint32)atol(temp);
540                         
541                         /* for some reason, we often have 0 as a primary group RID.
542                            Make sure that we treat this just as a 'default' value */
543                            
544                         if ( group_rid > 0 )
545                                 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
546                         else
547                                 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
548                 }
549         }
550
551         if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
552                 DEBUG(1, ("init_sam_from_ldap: no %s or %s attribute found for this user %s\n", 
553                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
554                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID),
555                         username));
556                 return False;
557         }
558
559         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
560                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp)) {
561                 /* leave as default */
562         } else {
563                 pass_last_set_time = (time_t) atol(temp);
564                 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
565         }
566
567         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
568                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp)) {
569                 /* leave as default */
570         } else {
571                 logon_time = (time_t) atol(temp);
572                 pdb_set_logon_time(sampass, logon_time, PDB_SET);
573         }
574
575         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
576                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp)) {
577                 /* leave as default */
578         } else {
579                 logoff_time = (time_t) atol(temp);
580                 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
581         }
582
583         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
584                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp)) {
585                 /* leave as default */
586         } else {
587                 kickoff_time = (time_t) atol(temp);
588                 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
589         }
590
591         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
592                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp)) {
593                 /* leave as default */
594         } else {
595                 pass_can_change_time = (time_t) atol(temp);
596                 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
597         }
598
599         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
600                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), 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, PDB_SET);
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 (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
614                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), fullname)) {
615                 if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
616                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_CN), fullname)) {
617                         /* leave as default */
618                 } else {
619                         pdb_set_fullname(sampass, fullname, PDB_SET);
620                 }
621         } else {
622                 pdb_set_fullname(sampass, fullname, PDB_SET);
623         }
624
625         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
626                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive)) 
627         {
628                 pdb_set_dir_drive( sampass, lp_logon_drive(), PDB_DEFAULT );
629         } else {
630                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
631         }
632
633         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
634                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir)) 
635         {
636                 pdb_set_homedir( sampass, 
637                         talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()),
638                         PDB_DEFAULT );
639         } else {
640                 pstrcpy( tmpstring, homedir );
641                 standard_sub_basic( username, tmpstring, sizeof(tmpstring) );
642                 pdb_set_homedir(sampass, tmpstring, PDB_SET);
643         }
644
645         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
646                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script)) 
647         {
648                 pdb_set_logon_script( sampass, 
649                         talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()), 
650                         PDB_DEFAULT );
651         } else {
652                 pstrcpy( tmpstring, logon_script );
653                 standard_sub_basic( username, tmpstring, sizeof(tmpstring) );
654                 pdb_set_logon_script(sampass, tmpstring, PDB_SET);
655         }
656
657         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
658                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path)) 
659         {
660                 pdb_set_profile_path( sampass, 
661                         talloc_sub_basic( sampass->mem_ctx, username, lp_logon_path()),
662                         PDB_DEFAULT );
663         } else {
664                 pstrcpy( tmpstring, profile_path );
665                 standard_sub_basic( username, tmpstring, sizeof(tmpstring) );
666                 pdb_set_profile_path(sampass, tmpstring, PDB_SET);
667         }
668
669         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
670                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), acct_desc)) 
671         {
672                 /* leave as default */
673         } else {
674                 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
675         }
676
677         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
678                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), workstations)) {
679                 /* leave as default */;
680         } else {
681                 pdb_set_workstations(sampass, workstations, PDB_SET);
682         }
683
684         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
685                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MUNGED_DIAL), munged_dial, sizeof(munged_dial))) {
686                 /* leave as default */;
687         } else {
688                 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
689         }
690         
691         /* FIXME: hours stuff should be cleaner */
692         
693         logon_divs = 168;
694         hours_len = 21;
695         memset(hours, 0xff, hours_len);
696
697         if (ldap_state->is_nds_ldap) {
698                 char *user_dn;
699                 int pwd_len;
700                 char clear_text_pw[512];
701
702                 /* Make call to Novell eDirectory ldap extension to get clear text password.
703                         NOTE: This will only work if we have an SSL connection to eDirectory. */
704                 user_dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
705                 if (user_dn != NULL) {
706                         DEBUG(3, ("init_sam_from_ldap: smbldap_get_dn(%s) returned '%s'\n", username, user_dn));
707
708                         pwd_len = sizeof(clear_text_pw);
709                         if (pdb_nds_get_password(ldap_state->smbldap_state, user_dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) {
710                                 nt_lm_owf_gen(clear_text_pw, smbntpwd, smblmpwd);
711                                 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
712                                         return False;
713                                 ZERO_STRUCT(smblmpwd);
714                                 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
715                                         return False;
716                                 ZERO_STRUCT(smbntpwd);
717                                 use_samba_attrs = False;
718                         }
719                 } else {
720                         DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username));
721                 }
722         }
723
724         if (use_samba_attrs) {
725                 if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, 
726                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) {
727                         /* leave as default */
728                 } else {
729                         pdb_gethexpwd(temp, smblmpwd);
730                         memset((char *)temp, '\0', strlen(temp)+1);
731                         if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
732                                 return False;
733                         ZERO_STRUCT(smblmpwd);
734                 }
735
736                 if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
737                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) {
738                         /* leave as default */
739                 } else {
740                         pdb_gethexpwd(temp, smbntpwd);
741                         memset((char *)temp, '\0', strlen(temp)+1);
742                         if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
743                                 return False;
744                         ZERO_STRUCT(smbntpwd);
745                 }
746         }
747
748         account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
749         if (pwHistLen > 0){
750                 uint8 *pwhist = NULL;
751                 int i;
752
753                 /* We can only store (sizeof(pstring)-1)/64 password history entries. */
754                 pwHistLen = MIN(pwHistLen, ((sizeof(temp)-1)/64));
755
756                 if ((pwhist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){
757                         DEBUG(0, ("init_sam_from_ldap: malloc failed!\n"));
758                         return False;
759                 }
760                 memset(pwhist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
761
762                 if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, 
763                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY), temp)) {
764                         /* leave as default - zeros */
765                 } else {
766                         BOOL hex_failed = False;
767                         for (i = 0; i < pwHistLen; i++){
768                                 /* Get the 16 byte salt. */
769                                 if (!pdb_gethexpwd(&temp[i*64], &pwhist[i*PW_HISTORY_ENTRY_LEN])) {
770                                         hex_failed = True;
771                                         break;
772                                 }
773                                 /* Get the 16 byte MD5 hash of salt+passwd. */
774                                 if (!pdb_gethexpwd(&temp[(i*64)+32],
775                                                 &pwhist[(i*PW_HISTORY_ENTRY_LEN)+PW_HISTORY_SALT_LEN])) {
776                                         hex_failed = True;
777                                         break;
778                                 }
779                         }
780                         if (hex_failed) {
781                                 DEBUG(0,("init_sam_from_ldap: Failed to get password history for user %s\n",
782                                         username));
783                                 memset(pwhist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
784                         }
785                 }
786                 if (!pdb_set_pw_history(sampass, pwhist, pwHistLen, PDB_SET)){
787                         SAFE_FREE(pwhist);
788                         return False;
789                 }
790                 SAFE_FREE(pwhist);
791         }
792
793         if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
794                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp)) {
795                 acct_ctrl |= ACB_NORMAL;
796         } else {
797                 acct_ctrl = pdb_decode_acct_ctrl(temp);
798
799                 if (acct_ctrl == 0)
800                         acct_ctrl |= ACB_NORMAL;
801
802                 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
803         }
804
805         pdb_set_hours_len(sampass, hours_len, PDB_SET);
806         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
807
808         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
809                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_BAD_PASSWORD_COUNT), temp)) {
810                         /* leave as default */
811         } else {
812                 bad_password_count = (uint32) atol(temp);
813                 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
814         }
815
816         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
817                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_BAD_PASSWORD_TIME), temp)) {
818                 /* leave as default */
819         } else {
820                 bad_password_time = (time_t) atol(temp);
821                 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
822         }
823
824
825         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
826                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_COUNT), temp)) {
827                         /* leave as default */
828         } else {
829                 logon_count = (uint32) atol(temp);
830                 pdb_set_logon_count(sampass, logon_count, PDB_SET);
831         }
832
833         /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
834
835         if(!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
836                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_HOURS), temp)) {
837                         /* leave as default */
838         } else {
839                 pdb_gethexhours(temp, hours);
840                 memset((char *)temp, '\0', strlen(temp) +1);
841                 pdb_set_hours(sampass, hours, PDB_SET);
842                 ZERO_STRUCT(hours);
843         }
844
845         /* check the timestamp of the cache vs ldap entry */
846         if (!(ldap_entry_time = ldapsam_get_entry_timestamp(ldap_state, 
847                                                             entry)))
848                 return True;
849
850         /* see if we have newer updates */
851         if (!(cache_entry = login_cache_read(sampass))) {
852                 DEBUG (9, ("No cache entry, bad count = %u, bad time = %u\n",
853                            (unsigned int)pdb_get_bad_password_count(sampass),
854                            (unsigned int)pdb_get_bad_password_time(sampass)));
855                 return True;
856         }
857
858         DEBUG(7, ("ldap time is %u, cache time is %u, bad time = %u\n", 
859                   (unsigned int)ldap_entry_time, (unsigned int)cache_entry->entry_timestamp, 
860                   (unsigned int)cache_entry->bad_password_time));
861
862         if (ldap_entry_time > cache_entry->entry_timestamp) {
863                 /* cache is older than directory , so
864                    we need to delete the entry but allow the 
865                    fields to be written out */
866                 login_cache_delentry(sampass);
867         } else {
868                 /* read cache in */
869                 pdb_set_acct_ctrl(sampass, 
870                                   pdb_get_acct_ctrl(sampass) | 
871                                   (cache_entry->acct_ctrl & ACB_AUTOLOCK),
872                                   PDB_SET);
873                 pdb_set_bad_password_count(sampass, 
874                                            cache_entry->bad_password_count, 
875                                            PDB_SET);
876                 pdb_set_bad_password_time(sampass, 
877                                           cache_entry->bad_password_time, 
878                                           PDB_SET);
879         }
880
881         SAFE_FREE(cache_entry);
882         return True;
883 }
884
885 /**********************************************************************
886  Initialize the ldap db from a SAM_ACCOUNT. Called on update.
887  (Based on init_buffer_from_sam in pdb_tdb.c)
888 *********************************************************************/
889
890 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, 
891                                 LDAPMessage *existing,
892                                 LDAPMod *** mods, SAM_ACCOUNT * sampass,
893                                 BOOL (*need_update)(const SAM_ACCOUNT *,
894                                                     enum pdb_elements))
895 {
896         pstring temp;
897         uint32 rid;
898
899         if (mods == NULL || sampass == NULL) {
900                 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
901                 return False;
902         }
903
904         *mods = NULL;
905
906         /* 
907          * took out adding "objectclass: sambaAccount"
908          * do this on a per-mod basis
909          */
910         if (need_update(sampass, PDB_USERNAME))
911                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, 
912                               "uid", pdb_get_username(sampass));
913
914         DEBUG(2, ("init_ldap_from_sam: Setting entry for user: %s\n", pdb_get_username(sampass)));
915
916         /* only update the RID if we actually need to */
917         if (need_update(sampass, PDB_USERSID)) {
918                 fstring sid_string;
919                 fstring dom_sid_string;
920                 const DOM_SID *user_sid = pdb_get_user_sid(sampass);
921                 
922                 switch ( ldap_state->schema_ver ) {
923                         case SCHEMAVER_SAMBAACCOUNT:
924                                 if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) {
925                                         DEBUG(1, ("init_ldap_from_sam: User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", 
926                                                 sid_to_string(sid_string, user_sid), 
927                                                 sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
928                                         return False;
929                                 }
930                                 slprintf(temp, sizeof(temp) - 1, "%i", rid);
931                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
932                                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), 
933                                         temp);
934                                 break;
935                                 
936                         case SCHEMAVER_SAMBASAMACCOUNT:
937                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
938                                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), 
939                                         sid_to_string(sid_string, user_sid));                                 
940                                 break;
941                                 
942                         default:
943                                 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
944                                 break;
945                 }               
946         }
947
948         /* we don't need to store the primary group RID - so leaving it
949            'free' to hang off the unix primary group makes life easier */
950
951         if (need_update(sampass, PDB_GROUPSID)) {
952                 fstring sid_string;
953                 fstring dom_sid_string;
954                 const DOM_SID *group_sid = pdb_get_group_sid(sampass);
955                 
956                 switch ( ldap_state->schema_ver ) {
957                         case SCHEMAVER_SAMBAACCOUNT:
958                                 if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) {
959                                         DEBUG(1, ("init_ldap_from_sam: User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
960                                                 sid_to_string(sid_string, group_sid),
961                                                 sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
962                                         return False;
963                                 }
964
965                                 slprintf(temp, sizeof(temp) - 1, "%i", rid);
966                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
967                                         get_userattr_key2string(ldap_state->schema_ver, 
968                                         LDAP_ATTR_PRIMARY_GROUP_RID), temp);
969                                 break;
970                                 
971                         case SCHEMAVER_SAMBASAMACCOUNT:
972                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
973                                         get_userattr_key2string(ldap_state->schema_ver, 
974                                         LDAP_ATTR_PRIMARY_GROUP_SID), sid_to_string(sid_string, group_sid));
975                                 break;
976                                 
977                         default:
978                                 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
979                                 break;
980                 }
981                 
982         }
983         
984         /* displayName, cn, and gecos should all be the same
985          *  most easily accomplished by giving them the same OID
986          *  gecos isn't set here b/c it should be handled by the 
987          *  add-user script
988          *  We change displayName only and fall back to cn if
989          *  it does not exist.
990          */
991
992         if (need_update(sampass, PDB_FULLNAME))
993                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
994                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), 
995                         pdb_get_fullname(sampass));
996
997         if (need_update(sampass, PDB_ACCTDESC))
998                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
999                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), 
1000                         pdb_get_acct_desc(sampass));
1001
1002         if (need_update(sampass, PDB_WORKSTATIONS))
1003                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1004                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), 
1005                         pdb_get_workstations(sampass));
1006         
1007         if (need_update(sampass, PDB_MUNGEDDIAL))
1008                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1009                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MUNGED_DIAL), 
1010                         pdb_get_munged_dial(sampass));
1011         
1012         if (need_update(sampass, PDB_SMBHOME))
1013                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1014                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), 
1015                         pdb_get_homedir(sampass));
1016                         
1017         if (need_update(sampass, PDB_DRIVE))
1018                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1019                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), 
1020                         pdb_get_dir_drive(sampass));
1021
1022         if (need_update(sampass, PDB_LOGONSCRIPT))
1023                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1024                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), 
1025                         pdb_get_logon_script(sampass));
1026
1027         if (need_update(sampass, PDB_PROFILE))
1028                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1029                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), 
1030                         pdb_get_profile_path(sampass));
1031
1032         slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
1033         if (need_update(sampass, PDB_LOGONTIME))
1034                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1035                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp);
1036
1037         slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
1038         if (need_update(sampass, PDB_LOGOFFTIME))
1039                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1040                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp);
1041
1042         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
1043         if (need_update(sampass, PDB_KICKOFFTIME))
1044                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1045                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
1046
1047         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
1048         if (need_update(sampass, PDB_CANCHANGETIME))
1049                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1050                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
1051
1052         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
1053         if (need_update(sampass, PDB_MUSTCHANGETIME))
1054                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1055                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp);
1056
1057
1058         if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))
1059                         || (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
1060
1061                 if (need_update(sampass, PDB_LMPASSWD)) {
1062                         const uchar *lm_pw =  pdb_get_lanman_passwd(sampass);
1063                         if (lm_pw) {
1064                                 pdb_sethexpwd(temp, lm_pw,
1065                                               pdb_get_acct_ctrl(sampass));
1066                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1067                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), 
1068                                                  temp);
1069                         } else {
1070                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1071                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), 
1072                                                  NULL);
1073                         }
1074                 }
1075                 if (need_update(sampass, PDB_NTPASSWD)) {
1076                         const uchar *nt_pw =  pdb_get_nt_passwd(sampass);
1077                         if (nt_pw) {
1078                                 pdb_sethexpwd(temp, nt_pw,
1079                                               pdb_get_acct_ctrl(sampass));
1080                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1081                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), 
1082                                                  temp);
1083                         } else {
1084                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1085                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), 
1086                                                  NULL);
1087                         }
1088                 }
1089
1090                 if (need_update(sampass, PDB_PWHISTORY)) {
1091                         uint32 pwHistLen = 0;
1092                         account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
1093                         if (pwHistLen == 0) {
1094                                 /* Remove any password history from the LDAP store. */
1095                                 memset(temp, '0', 64); /* NOTE !!!! '0' *NOT '\0' */
1096                                 temp[64] = '\0';
1097                         } else {
1098                                 int i; 
1099                                 uint32 currHistLen = 0;
1100                                 const uint8 *pwhist = pdb_get_pw_history(sampass, &currHistLen);
1101                                 if (pwhist != NULL) {
1102                                         /* We can only store (sizeof(pstring)-1)/64 password history entries. */
1103                                         pwHistLen = MIN(pwHistLen, ((sizeof(temp)-1)/64));
1104                                         for (i=0; i< pwHistLen && i < currHistLen; i++) {
1105                                                 /* Store the salt. */
1106                                                 pdb_sethexpwd(&temp[i*64], &pwhist[i*PW_HISTORY_ENTRY_LEN], 0);
1107                                                 /* Followed by the md5 hash of salt + md4 hash */
1108                                                 pdb_sethexpwd(&temp[(i*64)+32],
1109                                                         &pwhist[(i*PW_HISTORY_ENTRY_LEN)+PW_HISTORY_SALT_LEN], 0);
1110                                                 DEBUG(100, ("temp=%s\n", temp));
1111                                         }
1112                                 } 
1113                         }
1114                         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1115                                          get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY), 
1116                                          temp);
1117                 }
1118
1119                 if (need_update(sampass, PDB_PASSLASTSET)) {
1120                         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
1121                         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1122                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), 
1123                                 temp);
1124                 }
1125         }
1126
1127         if (need_update(sampass, PDB_HOURS)) {
1128                 const uint8 *hours = pdb_get_hours(sampass);
1129                 if (hours) {
1130                         pdb_sethexhours(temp, hours);
1131                         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct,
1132                                 existing,
1133                                 mods,
1134                                 get_userattr_key2string(ldap_state->schema_ver,
1135                                                 LDAP_ATTR_LOGON_HOURS),
1136                                 temp);
1137                 }
1138         }
1139
1140         if (need_update(sampass, PDB_ACCTCTRL))
1141                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1142                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), 
1143                         pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), NEW_PW_FORMAT_SPACE_PADDED_LEN));
1144
1145         /* password lockout cache: 
1146            - If we are now autolocking or clearing, we write to ldap
1147            - If we are clearing, we delete the cache entry
1148            - If the count is > 0, we update the cache
1149
1150            This even means when autolocking, we cache, just in case the
1151            update doesn't work, and we have to cache the autolock flag */
1152
1153         if (need_update(sampass, PDB_BAD_PASSWORD_COUNT))  /* &&
1154             need_update(sampass, PDB_BAD_PASSWORD_TIME)) */ {
1155                 uint16 badcount = pdb_get_bad_password_count(sampass);
1156                 time_t badtime = pdb_get_bad_password_time(sampass);
1157                 uint32 pol;
1158                 account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &pol);
1159
1160                 DEBUG(3, ("updating bad password fields, policy=%u, count=%u, time=%u\n",
1161                         (unsigned int)pol, (unsigned int)badcount, (unsigned int)badtime));
1162
1163                 if ((badcount >= pol) || (badcount == 0)) {
1164                         DEBUG(7, ("making mods to update ldap, count=%u, time=%u\n",
1165                                 (unsigned int)badcount, (unsigned int)badtime));
1166                         slprintf (temp, sizeof (temp) - 1, "%li", (long)badcount);
1167                         smbldap_make_mod(
1168                                 ldap_state->smbldap_state->ldap_struct,
1169                                 existing, mods, 
1170                                 get_userattr_key2string(
1171                                         ldap_state->schema_ver, 
1172                                         LDAP_ATTR_BAD_PASSWORD_COUNT),
1173                                 temp);
1174
1175                         slprintf (temp, sizeof (temp) - 1, "%li", badtime);
1176                         smbldap_make_mod(
1177                                 ldap_state->smbldap_state->ldap_struct, 
1178                                 existing, mods,
1179                                 get_userattr_key2string(
1180                                         ldap_state->schema_ver, 
1181                                         LDAP_ATTR_BAD_PASSWORD_TIME), 
1182                                 temp);
1183                 }
1184                 if (badcount == 0) {
1185                         DEBUG(7, ("bad password count is reset, deleting login cache entry for %s\n", pdb_get_nt_username(sampass)));
1186                         login_cache_delentry(sampass);
1187                 } else {
1188                         LOGIN_CACHE cache_entry;
1189
1190                         cache_entry.entry_timestamp = time(NULL);
1191                         cache_entry.acct_ctrl = pdb_get_acct_ctrl(sampass);
1192                         cache_entry.bad_password_count = badcount;
1193                         cache_entry.bad_password_time = badtime;
1194
1195                         DEBUG(7, ("Updating bad password count and time in login cache\n"));
1196                         login_cache_write(sampass, cache_entry);
1197                 }
1198         }
1199
1200         return True;
1201 }
1202
1203 /**********************************************************************
1204  Connect to LDAP server for password enumeration.
1205 *********************************************************************/
1206
1207 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint16 acb_mask)
1208 {
1209         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1210         int rc;
1211         pstring filter, suffix;
1212         const char **attr_list;
1213         BOOL machine_mask = False, user_mask = False;
1214
1215         pstr_sprintf( filter, "(&%s%s)", lp_ldap_filter(), 
1216                 get_objclass_filter(ldap_state->schema_ver));
1217         all_string_sub(filter, "%u", "*", sizeof(pstring));
1218
1219         machine_mask    = ((acb_mask != 0) && (acb_mask & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)));
1220         user_mask       = ((acb_mask != 0) && (acb_mask & ACB_NORMAL));
1221
1222         if (machine_mask) {
1223                 pstrcpy(suffix, lp_ldap_machine_suffix());
1224         } else if (user_mask) {
1225                 pstrcpy(suffix, lp_ldap_user_suffix());
1226         } else {
1227                 pstrcpy(suffix, lp_ldap_suffix());
1228         }
1229
1230         DEBUG(10,("ldapsam_setsampwent: LDAP Query for acb_mask 0x%x will use suffix %s\n", 
1231                 acb_mask, suffix));
1232
1233         attr_list = get_userattr_list(ldap_state->schema_ver);
1234         rc = smbldap_search(ldap_state->smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter, 
1235                             attr_list, 0, &ldap_state->result);
1236         free_attr_list( attr_list );
1237
1238         if (rc != LDAP_SUCCESS) {
1239                 DEBUG(0, ("ldapsam_setsampwent: LDAP search failed: %s\n", ldap_err2string(rc)));
1240                 DEBUG(3, ("ldapsam_setsampwent: Query was: %s, %s\n", suffix, filter));
1241                 ldap_msgfree(ldap_state->result);
1242                 ldap_state->result = NULL;
1243                 return NT_STATUS_UNSUCCESSFUL;
1244         }
1245
1246         DEBUG(2, ("ldapsam_setsampwent: %d entries in the base %s\n",
1247                 ldap_count_entries(ldap_state->smbldap_state->ldap_struct, 
1248                 ldap_state->result), suffix));
1249
1250         ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
1251                                  ldap_state->result);
1252         ldap_state->index = 0;
1253
1254         return NT_STATUS_OK;
1255 }
1256
1257 /**********************************************************************
1258  End enumeration of the LDAP password list.
1259 *********************************************************************/
1260
1261 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1262 {
1263         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1264         if (ldap_state->result) {
1265                 ldap_msgfree(ldap_state->result);
1266                 ldap_state->result = NULL;
1267         }
1268 }
1269
1270 /**********************************************************************
1271 Get the next entry in the LDAP password database.
1272 *********************************************************************/
1273
1274 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
1275 {
1276         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1277         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1278         BOOL bret = False;
1279
1280         while (!bret) {
1281                 if (!ldap_state->entry)
1282                         return ret;
1283                 
1284                 ldap_state->index++;
1285                 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
1286                 
1287                 ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
1288                                             ldap_state->entry); 
1289         }
1290
1291         return NT_STATUS_OK;
1292 }
1293
1294 static void append_attr(const char ***attr_list, const char *new_attr)
1295 {
1296         int i;
1297
1298         if (new_attr == NULL) {
1299                 return;
1300         }
1301
1302         for (i=0; (*attr_list)[i] != NULL; i++) {
1303                 ;
1304         }
1305
1306         (*attr_list) = SMB_REALLOC_ARRAY((*attr_list), const char *,  i+2);
1307         SMB_ASSERT((*attr_list) != NULL);
1308         (*attr_list)[i] = SMB_STRDUP(new_attr);
1309         (*attr_list)[i+1] = NULL;
1310 }
1311
1312 /**********************************************************************
1313 Get SAM_ACCOUNT entry from LDAP by username.
1314 *********************************************************************/
1315
1316 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
1317 {
1318         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1319         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1320         LDAPMessage *result = NULL;
1321         LDAPMessage *entry = NULL;
1322         int count;
1323         const char ** attr_list;
1324         int rc;
1325         
1326         attr_list = get_userattr_list( ldap_state->schema_ver );
1327         append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP));
1328         rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
1329         free_attr_list( attr_list );
1330
1331         if ( rc != LDAP_SUCCESS ) 
1332                 return NT_STATUS_NO_SUCH_USER;
1333         
1334         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1335         
1336         if (count < 1) {
1337                 DEBUG(4, ("ldapsam_getsampwnam: Unable to locate user [%s] count=%d\n", sname, count));
1338                 ldap_msgfree(result);
1339                 return NT_STATUS_NO_SUCH_USER;
1340         } else if (count > 1) {
1341                 DEBUG(1, ("ldapsam_getsampwnam: Duplicate entries for this user [%s] Failing. count=%d\n", sname, count));
1342                 ldap_msgfree(result);
1343                 return NT_STATUS_NO_SUCH_USER;
1344         }
1345
1346         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1347         if (entry) {
1348                 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1349                         DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1350                         ldap_msgfree(result);
1351                         return NT_STATUS_NO_SUCH_USER;
1352                 }
1353                 pdb_set_backend_private_data(user, result, 
1354                                              private_data_free_fn, 
1355                                              my_methods, PDB_CHANGED);
1356                 ret = NT_STATUS_OK;
1357         } else {
1358                 ldap_msgfree(result);
1359         }
1360         return ret;
1361 }
1362
1363 static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, 
1364                                    const DOM_SID *sid, LDAPMessage **result) 
1365 {
1366         int rc = -1;
1367         const char ** attr_list;
1368         uint32 rid;
1369
1370         switch ( ldap_state->schema_ver ) {
1371                 case SCHEMAVER_SAMBASAMACCOUNT:
1372                         attr_list = get_userattr_list(ldap_state->schema_ver);
1373                         append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP));
1374                         rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list);
1375                         free_attr_list( attr_list );
1376
1377                         if ( rc != LDAP_SUCCESS ) 
1378                                 return rc;
1379                         break;
1380                         
1381                 case SCHEMAVER_SAMBAACCOUNT:
1382                         if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) {
1383                                 return rc;
1384                         }
1385                 
1386                         attr_list = get_userattr_list(ldap_state->schema_ver);
1387                         rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list );
1388                         free_attr_list( attr_list );
1389
1390                         if ( rc != LDAP_SUCCESS ) 
1391                                 return rc;
1392                         break;
1393         }
1394         return rc;
1395 }
1396
1397 /**********************************************************************
1398  Get SAM_ACCOUNT entry from LDAP by SID.
1399 *********************************************************************/
1400
1401 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1402 {
1403         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1404         LDAPMessage *result = NULL;
1405         LDAPMessage *entry = NULL;
1406         int count;
1407         int rc;
1408         fstring sid_string;
1409
1410         rc = ldapsam_get_ldap_user_by_sid(ldap_state, 
1411                                           sid, &result); 
1412         if (rc != LDAP_SUCCESS)
1413                 return NT_STATUS_NO_SUCH_USER;
1414
1415         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1416         
1417         if (count < 1) {
1418                 DEBUG(4, ("ldapsam_getsampwsid: Unable to locate SID [%s] count=%d\n", sid_to_string(sid_string, sid),
1419                        count));
1420                 ldap_msgfree(result);
1421                 return NT_STATUS_NO_SUCH_USER;
1422         }  else if (count > 1) {
1423                 DEBUG(1, ("ldapsam_getsampwsid: More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid),
1424                        count));
1425                 ldap_msgfree(result);
1426                 return NT_STATUS_NO_SUCH_USER;
1427         }
1428
1429         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1430         if (!entry) {
1431                 ldap_msgfree(result);
1432                 return NT_STATUS_NO_SUCH_USER;
1433         }
1434
1435         if (!init_sam_from_ldap(ldap_state, user, entry)) {
1436                 DEBUG(1,("ldapsam_getsampwsid: init_sam_from_ldap failed!\n"));
1437                 ldap_msgfree(result);
1438                 return NT_STATUS_NO_SUCH_USER;
1439         }
1440
1441         pdb_set_backend_private_data(user, result, 
1442                                      private_data_free_fn, 
1443                                      my_methods, PDB_CHANGED);
1444         return NT_STATUS_OK;
1445 }       
1446
1447 static BOOL ldapsam_can_pwchange_exop(struct smbldap_state *ldap_state)
1448 {
1449         return smbldap_has_extension(ldap_state, LDAP_EXOP_MODIFY_PASSWD);
1450 }
1451
1452 /********************************************************************
1453  Do the actual modification - also change a plaintext passord if 
1454  it it set.
1455 **********************************************************************/
1456
1457 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, 
1458                                      SAM_ACCOUNT *newpwd, char *dn,
1459                                      LDAPMod **mods, int ldap_op, 
1460                                      BOOL (*need_update)(const SAM_ACCOUNT *, enum pdb_elements))
1461 {
1462         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1463         int rc;
1464         
1465         if (!my_methods || !newpwd || !dn) {
1466                 return NT_STATUS_INVALID_PARAMETER;
1467         }
1468         
1469         if (!mods) {
1470                 DEBUG(5,("ldapsam_modify_entry: mods is empty: nothing to modify\n"));
1471                 /* may be password change below however */
1472         } else {
1473                 switch(ldap_op) {
1474                         case LDAP_MOD_ADD: 
1475                                 smbldap_set_mod(&mods, LDAP_MOD_ADD, 
1476                                                 "objectclass", 
1477                                                 LDAP_OBJ_ACCOUNT);
1478                                 rc = smbldap_add(ldap_state->smbldap_state, 
1479                                                  dn, mods);
1480                                 break;
1481                         case LDAP_MOD_REPLACE: 
1482                                 rc = smbldap_modify(ldap_state->smbldap_state, 
1483                                                     dn ,mods);
1484                                 break;
1485                         default:        
1486                                 DEBUG(0,("ldapsam_modify_entry: Wrong LDAP operation type: %d!\n", 
1487                                          ldap_op));
1488                                 return NT_STATUS_INVALID_PARAMETER;
1489                 }
1490                 
1491                 if (rc!=LDAP_SUCCESS) {
1492                         char *ld_error = NULL;
1493                         ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1494                                         &ld_error);
1495                         DEBUG(1, ("ldapsam_modify_entry: Failed to %s user dn= %s with: %s\n\t%s\n",
1496                                ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1497                                dn, ldap_err2string(rc),
1498                                ld_error?ld_error:"unknown"));
1499                         SAFE_FREE(ld_error);
1500                         return NT_STATUS_UNSUCCESSFUL;
1501                 }  
1502         }
1503         
1504         if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
1505                         (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
1506                         need_update(newpwd, PDB_PLAINTEXT_PW) &&
1507                         (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1508                 BerElement *ber;
1509                 struct berval *bv;
1510                 char *retoid = NULL;
1511                 struct berval *retdata = NULL;
1512                 char *utf8_password;
1513                 char *utf8_dn;
1514
1515                 if (!ldap_state->is_nds_ldap) {
1516                         if (!ldapsam_can_pwchange_exop(ldap_state->smbldap_state)) {
1517                                 DEBUG(2, ("ldap password change requested, but LDAP "
1518                                           "server does not support it -- ignoring\n"));
1519                                 return NT_STATUS_OK;
1520                         }
1521                 }
1522
1523                 if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
1524                         return NT_STATUS_NO_MEMORY;
1525                 }
1526
1527                 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
1528                         return NT_STATUS_NO_MEMORY;
1529                 }
1530
1531                 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1532                         DEBUG(0,("ber_alloc_t returns NULL\n"));
1533                         SAFE_FREE(utf8_password);
1534                         return NT_STATUS_UNSUCCESSFUL;
1535                 }
1536
1537                 ber_printf (ber, "{");
1538                 ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, utf8_dn);
1539                 ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, utf8_password);
1540                 ber_printf (ber, "N}");
1541
1542                 if ((rc = ber_flatten (ber, &bv))<0) {
1543                         DEBUG(0,("ldapsam_modify_entry: ber_flatten returns a value <0\n"));
1544                         ber_free(ber,1);
1545                         SAFE_FREE(utf8_dn);
1546                         SAFE_FREE(utf8_password);
1547                         return NT_STATUS_UNSUCCESSFUL;
1548                 }
1549                 
1550                 SAFE_FREE(utf8_dn);
1551                 SAFE_FREE(utf8_password);
1552                 ber_free(ber, 1);
1553
1554                 if (!ldap_state->is_nds_ldap) {
1555                         rc = smbldap_extended_operation(ldap_state->smbldap_state, 
1556                                                         LDAP_EXOP_MODIFY_PASSWD,
1557                                                         bv, NULL, NULL, &retoid, 
1558                                                         &retdata);
1559                 } else {
1560                         rc = pdb_nds_set_password(ldap_state->smbldap_state, dn,
1561                                                         pdb_get_plaintext_passwd(newpwd));
1562                 }
1563                 if (rc != LDAP_SUCCESS) {
1564                         char *ld_error = NULL;
1565
1566                         if (rc == LDAP_OBJECT_CLASS_VIOLATION) {
1567                                 DEBUG(3, ("Could not set userPassword "
1568                                           "attribute due to an objectClass "
1569                                           "violation -- ignoring\n"));
1570                                 ber_bvfree(bv);
1571                                 return NT_STATUS_OK;
1572                         }
1573
1574                         ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1575                                         &ld_error);
1576                         DEBUG(0,("ldapsam_modify_entry: LDAP Password could not be changed for user %s: %s\n\t%s\n",
1577                                 pdb_get_username(newpwd), ldap_err2string(rc), ld_error?ld_error:"unknown"));
1578                         SAFE_FREE(ld_error);
1579                         ber_bvfree(bv);
1580                         return NT_STATUS_UNSUCCESSFUL;
1581                 } else {
1582                         DEBUG(3,("ldapsam_modify_entry: LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1583 #ifdef DEBUG_PASSWORD
1584                         DEBUG(100,("ldapsam_modify_entry: LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
1585 #endif    
1586                         if (retdata)
1587                                 ber_bvfree(retdata);
1588                         if (retoid)
1589                                 ber_memfree(retoid);
1590                 }
1591                 ber_bvfree(bv);
1592         }
1593         return NT_STATUS_OK;
1594 }
1595
1596 /**********************************************************************
1597  Delete entry from LDAP for username.
1598 *********************************************************************/
1599
1600 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1601 {
1602         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1603         const char *sname;
1604         int rc;
1605         LDAPMessage *result = NULL;
1606         NTSTATUS ret;
1607         const char **attr_list;
1608         fstring objclass;
1609
1610         if (!sam_acct) {
1611                 DEBUG(0, ("ldapsam_delete_sam_account: sam_acct was NULL!\n"));
1612                 return NT_STATUS_INVALID_PARAMETER;
1613         }
1614
1615         sname = pdb_get_username(sam_acct);
1616
1617         DEBUG (3, ("ldapsam_delete_sam_account: Deleting user %s from LDAP.\n", sname));
1618
1619         attr_list= get_userattr_delete_list( ldap_state->schema_ver );
1620         rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
1621
1622         if (rc != LDAP_SUCCESS)  {
1623                 free_attr_list( attr_list );
1624                 return NT_STATUS_NO_SUCH_USER;
1625         }
1626         
1627         switch ( ldap_state->schema_ver ) {
1628                 case SCHEMAVER_SAMBASAMACCOUNT:
1629                         fstrcpy( objclass, LDAP_OBJ_SAMBASAMACCOUNT );
1630                         break;
1631                         
1632                 case SCHEMAVER_SAMBAACCOUNT:
1633                         fstrcpy( objclass, LDAP_OBJ_SAMBAACCOUNT );
1634                         break;
1635                 default:
1636                         fstrcpy( objclass, "UNKNOWN" );
1637                         DEBUG(0,("ldapsam_delete_sam_account: Unknown schema version specified!\n"));
1638                                 break;
1639         }
1640
1641         ret = ldapsam_delete_entry(ldap_state, result, objclass, attr_list );
1642         ldap_msgfree(result);
1643         free_attr_list( attr_list );
1644
1645         return ret;
1646 }
1647
1648 /**********************************************************************
1649  Helper function to determine for update_sam_account whether
1650  we need LDAP modification.
1651 *********************************************************************/
1652
1653 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
1654                                enum pdb_elements element)
1655 {
1656         return IS_SAM_CHANGED(sampass, element);
1657 }
1658
1659 /**********************************************************************
1660  Update SAM_ACCOUNT.
1661 *********************************************************************/
1662
1663 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1664 {
1665         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1666         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1667         int rc = 0;
1668         char *dn;
1669         LDAPMessage *result = NULL;
1670         LDAPMessage *entry = NULL;
1671         LDAPMod **mods = NULL;
1672         const char **attr_list;
1673
1674         result = pdb_get_backend_private_data(newpwd, my_methods);
1675         if (!result) {
1676                 attr_list = get_userattr_list(ldap_state->schema_ver);
1677                 rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list );
1678                 free_attr_list( attr_list );
1679                 if (rc != LDAP_SUCCESS) {
1680                         return NT_STATUS_UNSUCCESSFUL;
1681                 }
1682                 pdb_set_backend_private_data(newpwd, result, private_data_free_fn, my_methods, PDB_CHANGED);
1683         }
1684
1685         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
1686                 DEBUG(0, ("ldapsam_update_sam_account: No user to modify!\n"));
1687                 return NT_STATUS_UNSUCCESSFUL;
1688         }
1689
1690         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1691         dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
1692         if (!dn) {
1693                 return NT_STATUS_UNSUCCESSFUL;
1694         }
1695
1696         DEBUG(4, ("ldapsam_update_sam_account: user %s to be modified has dn: %s\n", pdb_get_username(newpwd), dn));
1697
1698         if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1699                                 element_is_changed)) {
1700                 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1701                 SAFE_FREE(dn);
1702                 if (mods != NULL)
1703                         ldap_mods_free(mods,True);
1704                 return NT_STATUS_UNSUCCESSFUL;
1705         }
1706         
1707         if (mods == NULL) {
1708                 DEBUG(4,("ldapsam_update_sam_account: mods is empty: nothing to update for user: %s\n",
1709                          pdb_get_username(newpwd)));
1710                 SAFE_FREE(dn);
1711                 return NT_STATUS_OK;
1712         }
1713         
1714         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
1715         ldap_mods_free(mods,True);
1716         SAFE_FREE(dn);
1717
1718         if (!NT_STATUS_IS_OK(ret)) {
1719                 char *ld_error = NULL;
1720                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1721                                 &ld_error);
1722                 DEBUG(0,("ldapsam_update_sam_account: failed to modify user with uid = %s, error: %s (%s)\n",
1723                          pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
1724                 SAFE_FREE(ld_error);
1725                 return ret;
1726         }
1727
1728         DEBUG(2, ("ldapsam_update_sam_account: successfully modified uid = %s in the LDAP database\n",
1729                   pdb_get_username(newpwd)));
1730         return NT_STATUS_OK;
1731 }
1732
1733 /**********************************************************************
1734  Helper function to determine for update_sam_account whether
1735  we need LDAP modification.
1736  *********************************************************************/
1737
1738 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
1739                                       enum pdb_elements element)
1740 {
1741         return (IS_SAM_SET(sampass, element) ||
1742                 IS_SAM_CHANGED(sampass, element));
1743 }
1744
1745 /**********************************************************************
1746  Add SAM_ACCOUNT to LDAP.
1747 *********************************************************************/
1748
1749 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1750 {
1751         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1752         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1753         int rc;
1754         LDAPMessage     *result = NULL;
1755         LDAPMessage     *entry  = NULL;
1756         pstring         dn;
1757         LDAPMod         **mods = NULL;
1758         int             ldap_op = LDAP_MOD_REPLACE;
1759         uint32          num_result;
1760         const char      **attr_list;
1761         char            *escape_user;
1762         const char      *username = pdb_get_username(newpwd);
1763         const DOM_SID   *sid = pdb_get_user_sid(newpwd);
1764         pstring         filter;
1765         fstring         sid_string;
1766
1767         if (!username || !*username) {
1768                 DEBUG(0, ("ldapsam_add_sam_account: Cannot add user without a username!\n"));
1769                 return NT_STATUS_INVALID_PARAMETER;
1770         }
1771
1772         /* free this list after the second search or in case we exit on failure */
1773         attr_list = get_userattr_list(ldap_state->schema_ver);
1774
1775         rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
1776
1777         if (rc != LDAP_SUCCESS) {
1778                 free_attr_list( attr_list );
1779                 return NT_STATUS_UNSUCCESSFUL;
1780         }
1781
1782         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
1783                 DEBUG(0,("ldapsam_add_sam_account: User '%s' already in the base, with samba attributes\n", 
1784                          username));
1785                 ldap_msgfree(result);
1786                 free_attr_list( attr_list );
1787                 return NT_STATUS_UNSUCCESSFUL;
1788         }
1789         ldap_msgfree(result);
1790         result = NULL;
1791
1792         if (element_is_set_or_changed(newpwd, PDB_USERSID)) {
1793                 rc = ldapsam_get_ldap_user_by_sid(ldap_state, 
1794                                                   sid, &result); 
1795                 if (rc == LDAP_SUCCESS) {
1796                         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
1797                                 DEBUG(0,("ldapsam_add_sam_account: SID '%s' already in the base, with samba attributes\n", 
1798                                          sid_to_string(sid_string, sid)));
1799                                 free_attr_list( attr_list );
1800                                 ldap_msgfree(result);
1801                                 return NT_STATUS_UNSUCCESSFUL;
1802                         }
1803                         ldap_msgfree(result);
1804                 }
1805         }
1806
1807         /* does the entry already exist but without a samba attributes?
1808            we need to return the samba attributes here */
1809            
1810         escape_user = escape_ldap_string_alloc( username );
1811         pstrcpy( filter, lp_ldap_filter() );
1812         all_string_sub( filter, "%u", escape_user, sizeof(filter) );
1813         SAFE_FREE( escape_user );
1814
1815         rc = smbldap_search_suffix(ldap_state->smbldap_state, 
1816                                    filter, attr_list, &result);
1817         if ( rc != LDAP_SUCCESS ) {
1818                 free_attr_list( attr_list );
1819                 return NT_STATUS_UNSUCCESSFUL;
1820         }
1821
1822         num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1823         
1824         if (num_result > 1) {
1825                 DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
1826                 free_attr_list( attr_list );
1827                 ldap_msgfree(result);
1828                 return NT_STATUS_UNSUCCESSFUL;
1829         }
1830         
1831         /* Check if we need to update an existing entry */
1832         if (num_result == 1) {
1833                 char *tmp;
1834                 
1835                 DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
1836                 ldap_op = LDAP_MOD_REPLACE;
1837                 entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
1838                 tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
1839                 if (!tmp) {
1840                         free_attr_list( attr_list );
1841                         ldap_msgfree(result);
1842                         return NT_STATUS_UNSUCCESSFUL;
1843                 }
1844                 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1845                 SAFE_FREE(tmp);
1846
1847         } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) {
1848
1849                 /* There might be a SID for this account already - say an idmap entry */
1850
1851                 pstr_sprintf(filter, "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))", 
1852                          get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
1853                          sid_to_string(sid_string, sid),
1854                          LDAP_OBJ_IDMAP_ENTRY,
1855                          LDAP_OBJ_SID_ENTRY);
1856                 
1857                 /* free old result before doing a new search */
1858                 if (result != NULL) {
1859                         ldap_msgfree(result);
1860                         result = NULL;
1861                 }
1862                 rc = smbldap_search_suffix(ldap_state->smbldap_state, 
1863                                            filter, attr_list, &result);
1864                         
1865                 if ( rc != LDAP_SUCCESS ) {
1866                         free_attr_list( attr_list );
1867                         return NT_STATUS_UNSUCCESSFUL;
1868                 }
1869                 
1870                 num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1871                 
1872                 if (num_result > 1) {
1873                         DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
1874                         free_attr_list( attr_list );
1875                         ldap_msgfree(result);
1876                         return NT_STATUS_UNSUCCESSFUL;
1877                 }
1878                 
1879                 /* Check if we need to update an existing entry */
1880                 if (num_result == 1) {
1881                         char *tmp;
1882                         
1883                         DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
1884                         ldap_op = LDAP_MOD_REPLACE;
1885                         entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
1886                         tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
1887                         if (!tmp) {
1888                                 free_attr_list( attr_list );
1889                                 ldap_msgfree(result);
1890                                 return NT_STATUS_UNSUCCESSFUL;
1891                         }
1892                         slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1893                         SAFE_FREE(tmp);
1894                 }
1895         }
1896         
1897         free_attr_list( attr_list );
1898
1899         if (num_result == 0) {
1900                 /* Check if we need to add an entry */
1901                 DEBUG(3,("ldapsam_add_sam_account: Adding new user\n"));
1902                 ldap_op = LDAP_MOD_ADD;
1903                 if (username[strlen(username)-1] == '$') {
1904                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
1905                 } else {
1906                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
1907                 }
1908         }
1909
1910         if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1911                                 element_is_set_or_changed)) {
1912                 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1913                 ldap_msgfree(result);
1914                 if (mods != NULL)
1915                         ldap_mods_free(mods,True);
1916                 return NT_STATUS_UNSUCCESSFUL;          
1917         }
1918         
1919         ldap_msgfree(result);
1920
1921         if (mods == NULL) {
1922                 DEBUG(0,("ldapsam_add_sam_account: mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
1923                 return NT_STATUS_UNSUCCESSFUL;
1924         }
1925         switch ( ldap_state->schema_ver ) {
1926                 case SCHEMAVER_SAMBAACCOUNT:
1927                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT);
1928                         break;
1929                 case SCHEMAVER_SAMBASAMACCOUNT:
1930                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT);
1931                         break;
1932                 default:
1933                         DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
1934                         break;
1935         }
1936
1937         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
1938         if (!NT_STATUS_IS_OK(ret)) {
1939                 DEBUG(0,("ldapsam_add_sam_account: failed to modify/add user with uid = %s (dn = %s)\n",
1940                          pdb_get_username(newpwd),dn));
1941                 ldap_mods_free(mods, True);
1942                 return ret;
1943         }
1944
1945         DEBUG(2,("ldapsam_add_sam_account: added: uid == %s in the LDAP database\n", pdb_get_username(newpwd)));
1946         ldap_mods_free(mods, True);
1947         
1948         return NT_STATUS_OK;
1949 }
1950
1951 /**********************************************************************
1952  *********************************************************************/
1953
1954 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
1955                                      const char *filter,
1956                                      LDAPMessage ** result)
1957 {
1958         int scope = LDAP_SCOPE_SUBTREE;
1959         int rc;
1960         const char **attr_list;
1961
1962         attr_list = get_attr_list(groupmap_attr_list);
1963         rc = smbldap_search(ldap_state->smbldap_state, 
1964                             lp_ldap_group_suffix (), scope,
1965                             filter, attr_list, 0, result);
1966         free_attr_list( attr_list );
1967
1968         if (rc != LDAP_SUCCESS) {
1969                 char *ld_error = NULL;
1970                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1971                                 &ld_error);
1972                 DEBUG(0, ("ldapsam_search_one_group: "
1973                           "Problem during the LDAP search: LDAP error: %s (%s)\n",
1974                           ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
1975                 DEBUGADD(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
1976                           lp_ldap_group_suffix(), filter));
1977                 SAFE_FREE(ld_error);
1978         }
1979
1980         return rc;
1981 }
1982
1983 /**********************************************************************
1984  *********************************************************************/
1985
1986 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
1987                                  GROUP_MAP *map, LDAPMessage *entry)
1988 {
1989         pstring temp;
1990
1991         if (ldap_state == NULL || map == NULL || entry == NULL ||
1992                         ldap_state->smbldap_state->ldap_struct == NULL) {
1993                 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
1994                 return False;
1995         }
1996
1997         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
1998                         get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp)) {
1999                 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n", 
2000                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GIDNUMBER)));
2001                 return False;
2002         }
2003         DEBUG(2, ("init_group_from_ldap: Entry found for group: %s\n", temp));
2004
2005         map->gid = (gid_t)atol(temp);
2006
2007         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
2008                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp)) {
2009                 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n",
2010                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID)));
2011                 return False;
2012         }
2013         
2014         if (!string_to_sid(&map->sid, temp)) {
2015                 DEBUG(1, ("SID string [%s] could not be read as a valid SID\n", temp));
2016                 return False;
2017         }
2018
2019         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
2020                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp)) {
2021                 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n",
2022                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
2023                 return False;
2024         }
2025         map->sid_name_use = (enum SID_NAME_USE)atol(temp);
2026
2027         if ((map->sid_name_use < SID_NAME_USER) ||
2028                         (map->sid_name_use > SID_NAME_UNKNOWN)) {
2029                 DEBUG(0, ("init_group_from_ldap: Unknown Group type: %d\n", map->sid_name_use));
2030                 return False;
2031         }
2032
2033         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
2034                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp)) {
2035                 temp[0] = '\0';
2036                 if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
2037                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp)) 
2038                 {
2039                         DEBUG(0, ("init_group_from_ldap: Attributes cn not found either \
2040 for gidNumber(%lu)\n",(unsigned long)map->gid));
2041                         return False;
2042                 }
2043         }
2044         fstrcpy(map->nt_name, temp);
2045
2046         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
2047                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp)) {
2048                 temp[0] = '\0';
2049         }
2050         fstrcpy(map->comment, temp);
2051
2052         return True;
2053 }
2054
2055 /**********************************************************************
2056  *********************************************************************/
2057
2058 static BOOL init_ldap_from_group(LDAP *ldap_struct,
2059                                  LDAPMessage *existing,
2060                                  LDAPMod ***mods,
2061                                  const GROUP_MAP *map)
2062 {
2063         pstring tmp;
2064
2065         if (mods == NULL || map == NULL) {
2066                 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2067                 return False;
2068         }
2069
2070         *mods = NULL;
2071
2072         sid_to_string(tmp, &map->sid);
2073
2074         smbldap_make_mod(ldap_struct, existing, mods, 
2075                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp);
2076         pstr_sprintf(tmp, "%i", map->sid_name_use);
2077         smbldap_make_mod(ldap_struct, existing, mods, 
2078                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp);
2079
2080         smbldap_make_mod(ldap_struct, existing, mods, 
2081                 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name);
2082         smbldap_make_mod(ldap_struct, existing, mods, 
2083                 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment);
2084
2085         return True;
2086 }
2087
2088 /**********************************************************************
2089  *********************************************************************/
2090
2091 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2092                                  const char *filter,
2093                                  GROUP_MAP *map)
2094 {
2095         struct ldapsam_privates *ldap_state =
2096                 (struct ldapsam_privates *)methods->private_data;
2097         LDAPMessage *result = NULL;
2098         LDAPMessage *entry = NULL;
2099         int count;
2100
2101         if (ldapsam_search_one_group(ldap_state, filter, &result)
2102             != LDAP_SUCCESS) {
2103                 return NT_STATUS_NO_SUCH_GROUP;
2104         }
2105
2106         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
2107
2108         if (count < 1) {
2109                 DEBUG(4, ("ldapsam_getgroup: Did not find group\n"));
2110                 ldap_msgfree(result);
2111                 return NT_STATUS_NO_SUCH_GROUP;
2112         }
2113
2114         if (count > 1) {
2115                 DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: count=%d\n",
2116                           filter, count));
2117                 ldap_msgfree(result);
2118                 return NT_STATUS_NO_SUCH_GROUP;
2119         }
2120
2121         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
2122
2123         if (!entry) {
2124                 ldap_msgfree(result);
2125                 return NT_STATUS_UNSUCCESSFUL;
2126         }
2127
2128         if (!init_group_from_ldap(ldap_state, map, entry)) {
2129                 DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for group filter %s\n",
2130                           filter));
2131                 ldap_msgfree(result);
2132                 return NT_STATUS_NO_SUCH_GROUP;
2133         }
2134
2135         ldap_msgfree(result);
2136         return NT_STATUS_OK;
2137 }
2138
2139 /**********************************************************************
2140  *********************************************************************/
2141
2142 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2143                                  DOM_SID sid)
2144 {
2145         pstring filter;
2146
2147         pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
2148                 LDAP_OBJ_GROUPMAP, 
2149                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID),
2150                 sid_string_static(&sid));
2151
2152         return ldapsam_getgroup(methods, filter, map);
2153 }
2154
2155 /**********************************************************************
2156  *********************************************************************/
2157
2158 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2159                                  gid_t gid)
2160 {
2161         pstring filter;
2162
2163         pstr_sprintf(filter, "(&(objectClass=%s)(%s=%d))",
2164                 LDAP_OBJ_GROUPMAP,
2165                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
2166                 gid);
2167
2168         return ldapsam_getgroup(methods, filter, map);
2169 }
2170
2171 /**********************************************************************
2172  *********************************************************************/
2173
2174 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2175                                  const char *name)
2176 {
2177         pstring filter;
2178         char *escape_name = escape_ldap_string_alloc(name);
2179
2180         if (!escape_name) {
2181                 return NT_STATUS_NO_MEMORY;
2182         }
2183
2184         pstr_sprintf(filter, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
2185                 LDAP_OBJ_GROUPMAP,
2186                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name,
2187                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), escape_name);
2188
2189         SAFE_FREE(escape_name);
2190
2191         return ldapsam_getgroup(methods, filter, map);
2192 }
2193
2194 static void add_rid_to_array_unique(TALLOC_CTX *mem_ctx,
2195                                     uint32 rid, uint32 **rids, int *num)
2196 {
2197         int i;
2198
2199         for (i=0; i<*num; i++) {
2200                 if ((*rids)[i] == rid)
2201                         return;
2202         }
2203         
2204         *rids = TALLOC_REALLOC_ARRAY(mem_ctx, *rids, uint32, *num+1);
2205
2206         if (*rids == NULL)
2207                 return;
2208
2209         (*rids)[*num] = rid;
2210         *num += 1;
2211 }
2212
2213 static BOOL ldapsam_extract_rid_from_entry(LDAP *ldap_struct,
2214                                            LDAPMessage *entry,
2215                                            const DOM_SID *domain_sid,
2216                                            uint32 *rid)
2217 {
2218         fstring str;
2219         DOM_SID sid;
2220
2221         if (!smbldap_get_single_attribute(ldap_struct, entry, "sambaSID",
2222                                           str, sizeof(str)-1)) {
2223                 DEBUG(10, ("Could not find sambaSID attribute\n"));
2224                 return False;
2225         }
2226
2227         if (!string_to_sid(&sid, str)) {
2228                 DEBUG(10, ("Could not convert string %s to sid\n", str));
2229                 return False;
2230         }
2231
2232         if (sid_compare_domain(&sid, domain_sid) != 0) {
2233                 DEBUG(10, ("SID %s is not in expected domain %s\n",
2234                            str, sid_string_static(domain_sid)));
2235                 return False;
2236         }
2237
2238         if (!sid_peek_rid(&sid, rid)) {
2239                 DEBUG(10, ("Could not peek into RID\n"));
2240                 return False;
2241         }
2242
2243         return True;
2244 }
2245
2246 static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
2247                                            TALLOC_CTX *mem_ctx,
2248                                            const DOM_SID *group,
2249                                            uint32 **member_rids,
2250                                            int *num_members)
2251 {
2252         struct ldapsam_privates *ldap_state =
2253                 (struct ldapsam_privates *)methods->private_data;
2254         struct smbldap_state *conn = ldap_state->smbldap_state;
2255         pstring filter;
2256         int rc, count;
2257         LDAPMessage *msg = NULL;
2258         LDAPMessage *entry;
2259         char **values = NULL;
2260         char **memberuid;
2261         char *sid_filter = NULL;
2262         char *tmp;
2263         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2264
2265         if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
2266                 return pdb_default_enum_group_members(methods, mem_ctx, group,
2267                                                       member_rids,
2268                                                       num_members);
2269
2270         *member_rids = NULL;
2271         *num_members = 0;
2272
2273         pstr_sprintf(filter,
2274                      "(&(objectClass=sambaSamAccount)"
2275                      "(sambaPrimaryGroupSid=%s))",
2276                      sid_string_static(group));
2277
2278         {
2279                 const char *attrs[] = { "sambaSID", NULL };
2280                 rc = smbldap_search(conn, lp_ldap_user_suffix(),
2281                                     LDAP_SCOPE_SUBTREE, filter, attrs, 0,
2282                                     &msg);
2283         }
2284
2285         if (rc != LDAP_SUCCESS)
2286                 goto done;
2287
2288         for (entry = ldap_first_entry(conn->ldap_struct, msg);
2289              entry != NULL;
2290              entry = ldap_next_entry(conn->ldap_struct, entry))
2291         {
2292                 uint32 rid;
2293
2294                 if (!ldapsam_extract_rid_from_entry(conn->ldap_struct,
2295                                                     entry,
2296                                                     get_global_sam_sid(),
2297                                                     &rid)) {
2298                         DEBUG(2, ("Could not find sid from ldap entry\n"));
2299                         continue;
2300                 }
2301
2302                 add_rid_to_array_unique(mem_ctx, rid, member_rids,
2303                                         num_members);
2304         }
2305
2306         if (msg != NULL)
2307                 ldap_msgfree(msg);
2308
2309         pstr_sprintf(filter,
2310                      "(&(objectClass=sambaGroupMapping)"
2311                      "(objectClass=posixGroup)"
2312                      "(sambaSID=%s))",
2313                      sid_string_static(group));
2314
2315         {
2316                 const char *attrs[] = { "memberUid", NULL };
2317                 rc = smbldap_search(conn, lp_ldap_group_suffix(),
2318                                     LDAP_SCOPE_SUBTREE, filter, attrs, 0,
2319                                     &msg);
2320         }
2321
2322         if (rc != LDAP_SUCCESS)
2323                 goto done;
2324
2325         count = ldap_count_entries(conn->ldap_struct, msg);
2326
2327         if (count > 1) {
2328                 DEBUG(1, ("Found more than one groupmap entry for %s\n",
2329                           sid_string_static(group)));
2330                 goto done;
2331         }
2332
2333         if (count == 0) {
2334                 result = NT_STATUS_OK;
2335                 goto done;
2336         }
2337
2338         entry = ldap_first_entry(conn->ldap_struct, msg);
2339         if (entry == NULL)
2340                 goto done;
2341
2342         values = ldap_get_values(conn->ldap_struct, msg, "memberUid");
2343         if (values == NULL) {
2344                 result = NT_STATUS_OK;
2345                 goto done;
2346         }
2347
2348         sid_filter = strdup("(&(objectClass=sambaSamAccount)(|");
2349         if (sid_filter == NULL) {
2350                 result = NT_STATUS_NO_MEMORY;
2351                 goto done;
2352         }
2353
2354         for (memberuid = values; *memberuid != NULL; memberuid += 1) {
2355                 tmp = sid_filter;
2356                 asprintf(&sid_filter, "%s(uid=%s)", tmp, *memberuid);
2357                 free(tmp);
2358                 if (sid_filter == NULL) {
2359                         result = NT_STATUS_NO_MEMORY;
2360                         goto done;
2361                 }
2362         }
2363
2364         tmp = sid_filter;
2365         asprintf(&sid_filter, "%s))", sid_filter);
2366         free(tmp);
2367         if (sid_filter == NULL) {
2368                 result = NT_STATUS_NO_MEMORY;
2369                 goto done;
2370         }
2371
2372         {
2373                 const char *attrs[] = { "sambaSID", NULL };
2374                 rc = smbldap_search(conn, lp_ldap_user_suffix(),
2375                                     LDAP_SCOPE_SUBTREE, sid_filter, attrs, 0,
2376                                     &msg);
2377         }
2378
2379         if (rc != LDAP_SUCCESS)
2380                 goto done;
2381
2382         for (entry = ldap_first_entry(conn->ldap_struct, msg);
2383              entry != NULL;
2384              entry = ldap_next_entry(conn->ldap_struct, entry))
2385         {
2386                 fstring str;
2387                 DOM_SID sid;
2388                 uint32 rid;
2389
2390                 if (!smbldap_get_single_attribute(conn->ldap_struct,
2391                                                   entry, "sambaSID",
2392                                                   str, sizeof(str)-1))
2393                         continue;
2394
2395                 if (!string_to_sid(&sid, str))
2396                         goto done;
2397
2398                 if (!sid_check_is_in_our_domain(&sid)) {
2399                         DEBUG(1, ("Inconsistent SAM -- group member uid not "
2400                                   "in our domain\n"));
2401                         continue;
2402                 }
2403
2404                 sid_peek_rid(&sid, &rid);
2405
2406                 add_rid_to_array_unique(mem_ctx, rid, member_rids,
2407                                         num_members);
2408         }
2409
2410         result = NT_STATUS_OK;
2411         
2412  done:
2413         SAFE_FREE(sid_filter);
2414
2415         if (values != NULL)
2416                 ldap_value_free(values);
2417
2418         if (msg != NULL)
2419                 ldap_msgfree(msg);
2420
2421         return result;
2422 }
2423
2424 static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
2425                                                const char *username,
2426                                                gid_t primary_gid,
2427                                                DOM_SID **sids, gid_t **gids,
2428                                                int *num_groups)
2429 {
2430         struct ldapsam_privates *ldap_state =
2431                 (struct ldapsam_privates *)methods->private_data;
2432         struct smbldap_state *conn = ldap_state->smbldap_state;
2433         pstring filter;
2434         const char *attrs[] = { "gidNumber", "sambaSID", NULL };
2435         char *escape_name;
2436         int rc;
2437         LDAPMessage *msg = NULL;
2438         LDAPMessage *entry;
2439         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2440         int num_sids, num_gids;
2441
2442         if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
2443                 return pdb_default_enum_group_memberships(methods, username,
2444                                                           primary_gid, sids,
2445                                                           gids, num_groups);
2446
2447         *sids = NULL;
2448         num_sids = 0;
2449
2450         escape_name = escape_ldap_string_alloc(username);
2451
2452         if (escape_name == NULL)
2453                 return NT_STATUS_NO_MEMORY;
2454
2455         pstr_sprintf(filter, "(&(objectClass=posixGroup)"
2456                      "(|(memberUid=%s)(gidNumber=%d)))",
2457                      username, primary_gid);
2458
2459         rc = smbldap_search(conn, lp_ldap_group_suffix(),
2460                             LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg);
2461
2462         if (rc != LDAP_SUCCESS)
2463                 goto done;
2464
2465         num_gids = 0;
2466         *gids = NULL;
2467
2468         num_sids = 0;
2469         *sids = NULL;
2470
2471         /* We need to add the primary group as the first gid/sid */
2472
2473         add_gid_to_array_unique(NULL, primary_gid, gids, &num_gids);
2474
2475         /* This sid will be replaced later */
2476
2477         add_sid_to_array_unique(NULL, &global_sid_NULL, sids, &num_sids);
2478
2479         for (entry = ldap_first_entry(conn->ldap_struct, msg);
2480              entry != NULL;
2481              entry = ldap_next_entry(conn->ldap_struct, entry))
2482         {
2483                 fstring str;
2484                 DOM_SID sid;
2485                 gid_t gid;
2486                 char *end;
2487
2488                 if (!smbldap_get_single_attribute(conn->ldap_struct,
2489                                                   entry, "sambaSID",
2490                                                   str, sizeof(str)-1))
2491                         continue;
2492
2493                 if (!string_to_sid(&sid, str))
2494                         goto done;
2495
2496                 if (!smbldap_get_single_attribute(conn->ldap_struct,
2497                                                   entry, "gidNumber",
2498                                                   str, sizeof(str)-1))
2499                         continue;
2500
2501                 gid = strtoul(str, &end, 10);
2502
2503                 if (PTR_DIFF(end, str) != strlen(str))
2504                         goto done;
2505
2506                 if (gid == primary_gid) {
2507                         sid_copy(&(*sids)[0], &sid);
2508                 } else {
2509                         add_gid_to_array_unique(NULL, gid, gids, &num_gids);
2510                         add_sid_to_array_unique(NULL, &sid, sids, &num_sids);
2511                 }
2512         }
2513
2514         if (sid_compare(&global_sid_NULL, &(*sids)[0]) == 0) {
2515                 DEBUG(3, ("primary group of [%s] not found\n", username));
2516                 goto done;
2517         }
2518
2519         *num_groups = num_sids;
2520
2521         result = NT_STATUS_OK;
2522
2523  done:
2524
2525         SAFE_FREE(escape_name);
2526         if (msg != NULL)
2527                 ldap_msgfree(msg);
2528
2529         return result;
2530 }
2531
2532 /**********************************************************************
2533  *********************************************************************/
2534
2535 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
2536                                            gid_t gid,
2537                                            LDAPMessage **result)
2538 {
2539         pstring filter;
2540
2541         pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%d))", 
2542                 LDAP_OBJ_POSIXGROUP, LDAP_OBJ_IDMAP_ENTRY,
2543                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
2544                 gid);
2545
2546         return ldapsam_search_one_group(ldap_state, filter, result);
2547 }
2548
2549 /**********************************************************************
2550  *********************************************************************/
2551
2552 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2553                                                 GROUP_MAP *map)
2554 {
2555         struct ldapsam_privates *ldap_state =
2556                 (struct ldapsam_privates *)methods->private_data;
2557         LDAPMessage *result = NULL;
2558         LDAPMod **mods = NULL;
2559         int count;
2560
2561         char *tmp;
2562         pstring dn;
2563         LDAPMessage *entry;
2564
2565         GROUP_MAP dummy;
2566
2567         int rc;
2568
2569         if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
2570                                              map->gid))) {
2571                 DEBUG(0, ("ldapsam_add_group_mapping_entry: Group %ld already exists in LDAP\n", (unsigned long)map->gid));
2572                 return NT_STATUS_UNSUCCESSFUL;
2573         }
2574
2575         rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2576         if (rc != LDAP_SUCCESS) {
2577                 ldap_msgfree(result);
2578                 return NT_STATUS_UNSUCCESSFUL;
2579         }
2580
2581         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
2582
2583         if ( count == 0 ) {
2584                 /* There's no posixGroup account, let's try to find an
2585                  * appropriate idmap entry for aliases */
2586
2587                 pstring suffix;
2588                 pstring filter;
2589                 const char **attr_list;
2590
2591                 ldap_msgfree(result);
2592
2593                 pstrcpy( suffix, lp_ldap_idmap_suffix() );
2594                 pstr_sprintf(filter, "(&(objectClass=%s)(%s=%d))",
2595                              LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_GIDNUMBER,
2596                              map->gid);
2597                 
2598                 attr_list = get_attr_list( sidmap_attr_list );
2599                 rc = smbldap_search(ldap_state->smbldap_state, suffix,
2600                                     LDAP_SCOPE_SUBTREE, filter, attr_list,
2601                                     0, &result);
2602
2603                 free_attr_list(attr_list);
2604
2605                 if (rc != LDAP_SUCCESS) {
2606                         DEBUG(3,("Failure looking up entry (%s)\n",
2607                                  ldap_err2string(rc) ));
2608                         ldap_msgfree(result);
2609                         return NT_STATUS_UNSUCCESSFUL;
2610                 }
2611         }
2612                            
2613         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
2614         if ( count == 0 ) {
2615                 ldap_msgfree(result);
2616                 return NT_STATUS_UNSUCCESSFUL;
2617         }
2618
2619         if (count > 1) {
2620                 DEBUG(2, ("ldapsam_add_group_mapping_entry: Group %lu must exist exactly once in LDAP\n",
2621                           (unsigned long)map->gid));
2622                 ldap_msgfree(result);
2623                 return NT_STATUS_UNSUCCESSFUL;
2624         }
2625
2626         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
2627         tmp = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
2628         if (!tmp) {
2629                 ldap_msgfree(result);
2630                 return NT_STATUS_UNSUCCESSFUL;
2631         }
2632         pstrcpy(dn, tmp);
2633         SAFE_FREE(tmp);
2634
2635         if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
2636                                   result, &mods, map)) {
2637                 DEBUG(0, ("ldapsam_add_group_mapping_entry: init_ldap_from_group failed!\n"));
2638                 ldap_mods_free(mods, True);
2639                 ldap_msgfree(result);
2640                 return NT_STATUS_UNSUCCESSFUL;
2641         }
2642
2643         ldap_msgfree(result);
2644
2645         if (mods == NULL) {
2646                 DEBUG(0, ("ldapsam_add_group_mapping_entry: mods is empty\n"));
2647                 return NT_STATUS_UNSUCCESSFUL;
2648         }
2649
2650         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP );
2651
2652         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
2653         ldap_mods_free(mods, True);
2654
2655         if (rc != LDAP_SUCCESS) {
2656                 char *ld_error = NULL;
2657                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2658                                 &ld_error);
2659                 DEBUG(0, ("ldapsam_add_group_mapping_entry: failed to add group %lu error: %s (%s)\n", (unsigned long)map->gid, 
2660                           ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2661                 SAFE_FREE(ld_error);
2662                 return NT_STATUS_UNSUCCESSFUL;
2663         }
2664
2665         DEBUG(2, ("ldapsam_add_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
2666         return NT_STATUS_OK;
2667 }
2668
2669 /**********************************************************************
2670  *********************************************************************/
2671
2672 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
2673                                                    GROUP_MAP *map)
2674 {
2675         struct ldapsam_privates *ldap_state =
2676                 (struct ldapsam_privates *)methods->private_data;
2677         int rc;
2678         char *dn = NULL;
2679         LDAPMessage *result = NULL;
2680         LDAPMessage *entry = NULL;
2681         LDAPMod **mods = NULL;
2682
2683         rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2684
2685         if (rc != LDAP_SUCCESS) {
2686                 return NT_STATUS_UNSUCCESSFUL;
2687         }
2688
2689         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
2690                 DEBUG(0, ("ldapsam_update_group_mapping_entry: No group to modify!\n"));
2691                 ldap_msgfree(result);
2692                 return NT_STATUS_UNSUCCESSFUL;
2693         }
2694
2695         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
2696
2697         if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
2698                                   result, &mods, map)) {
2699                 DEBUG(0, ("ldapsam_update_group_mapping_entry: init_ldap_from_group failed\n"));
2700                 ldap_msgfree(result);
2701                 if (mods != NULL)
2702                         ldap_mods_free(mods,True);
2703                 return NT_STATUS_UNSUCCESSFUL;
2704         }
2705
2706         if (mods == NULL) {
2707                 DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: nothing to do\n"));
2708                 ldap_msgfree(result);
2709                 return NT_STATUS_OK;
2710         }
2711
2712         dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
2713         if (!dn) {
2714                 ldap_msgfree(result);
2715                 return NT_STATUS_UNSUCCESSFUL;
2716         }
2717         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
2718         SAFE_FREE(dn);
2719
2720         ldap_mods_free(mods, True);
2721         ldap_msgfree(result);
2722
2723         if (rc != LDAP_SUCCESS) {
2724                 char *ld_error = NULL;
2725                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2726                                 &ld_error);
2727                 DEBUG(0, ("ldapsam_update_group_mapping_entry: failed to modify group %lu error: %s (%s)\n", (unsigned long)map->gid, 
2728                           ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2729                 SAFE_FREE(ld_error);
2730                 return NT_STATUS_UNSUCCESSFUL;
2731         }
2732
2733         DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
2734         return NT_STATUS_OK;
2735 }
2736
2737 /**********************************************************************
2738  *********************************************************************/
2739
2740 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2741                                                    DOM_SID sid)
2742 {
2743         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)methods->private_data;
2744         pstring sidstring, filter;
2745         LDAPMessage *result = NULL;
2746         int rc;
2747         NTSTATUS ret;
2748         const char **attr_list;
2749
2750         sid_to_string(sidstring, &sid);
2751         
2752         pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", 
2753                 LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID, sidstring);
2754
2755         rc = ldapsam_search_one_group(ldap_state, filter, &result);
2756
2757         if (rc != LDAP_SUCCESS) {
2758                 return NT_STATUS_NO_SUCH_GROUP;
2759         }
2760
2761         attr_list = get_attr_list( groupmap_attr_list_to_delete );
2762         ret = ldapsam_delete_entry(ldap_state, result, LDAP_OBJ_GROUPMAP, attr_list);
2763         free_attr_list ( attr_list );
2764
2765         ldap_msgfree(result);
2766
2767         return ret;
2768 }
2769
2770 /**********************************************************************
2771  *********************************************************************/
2772
2773 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
2774 {
2775         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2776         fstring filter;
2777         int rc;
2778         const char **attr_list;
2779
2780         pstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
2781         attr_list = get_attr_list( groupmap_attr_list );
2782         rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
2783                             LDAP_SCOPE_SUBTREE, filter,
2784                             attr_list, 0, &ldap_state->result);
2785         free_attr_list( attr_list );
2786
2787         if (rc != LDAP_SUCCESS) {
2788                 DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n", ldap_err2string(rc)));
2789                 DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n", lp_ldap_group_suffix(), filter));
2790                 ldap_msgfree(ldap_state->result);
2791                 ldap_state->result = NULL;
2792                 return NT_STATUS_UNSUCCESSFUL;
2793         }
2794
2795         DEBUG(2, ("ldapsam_setsamgrent: %d entries in the base!\n",
2796                   ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
2797                                      ldap_state->result)));
2798
2799         ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result);
2800         ldap_state->index = 0;
2801
2802         return NT_STATUS_OK;
2803 }
2804
2805 /**********************************************************************
2806  *********************************************************************/
2807
2808 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2809 {
2810         ldapsam_endsampwent(my_methods);
2811 }
2812
2813 /**********************************************************************
2814  *********************************************************************/
2815
2816 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
2817                                     GROUP_MAP *map)
2818 {
2819         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2820         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2821         BOOL bret = False;
2822
2823         while (!bret) {
2824                 if (!ldap_state->entry)
2825                         return ret;
2826                 
2827                 ldap_state->index++;
2828                 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
2829                 
2830                 ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
2831                                             ldap_state->entry); 
2832         }
2833
2834         return NT_STATUS_OK;
2835 }
2836
2837 /**********************************************************************
2838  *********************************************************************/
2839
2840 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
2841                                            enum SID_NAME_USE sid_name_use,
2842                                            GROUP_MAP **rmap, int *num_entries,
2843                                            BOOL unix_only)
2844 {
2845         GROUP_MAP map;
2846         GROUP_MAP *mapt;
2847         int entries = 0;
2848
2849         *num_entries = 0;
2850         *rmap = NULL;
2851
2852         if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
2853                 DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open passdb\n"));
2854                 return NT_STATUS_ACCESS_DENIED;
2855         }
2856
2857         while (NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, &map))) {
2858                 if (sid_name_use != SID_NAME_UNKNOWN &&
2859                     sid_name_use != map.sid_name_use) {
2860                         DEBUG(11,("ldapsam_enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
2861                         continue;
2862                 }
2863                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
2864                         DEBUG(11,("ldapsam_enum_group_mapping: group %s is non mapped\n", map.nt_name));
2865                         continue;
2866                 }
2867
2868                 mapt=SMB_REALLOC_ARRAY((*rmap), GROUP_MAP, entries+1);
2869                 if (!mapt) {
2870                         DEBUG(0,("ldapsam_enum_group_mapping: Unable to enlarge group map!\n"));
2871                         SAFE_FREE(*rmap);
2872                         return NT_STATUS_UNSUCCESSFUL;
2873                 }
2874                 else
2875                         (*rmap) = mapt;
2876
2877                 mapt[entries] = map;
2878
2879                 entries += 1;
2880
2881         }
2882         ldapsam_endsamgrent(methods);
2883
2884         *num_entries = entries;
2885
2886         return NT_STATUS_OK;
2887 }
2888
2889 static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
2890                                         const DOM_SID *alias,
2891                                         const DOM_SID *member,
2892                                         int modop)
2893 {
2894         struct ldapsam_privates *ldap_state =
2895                 (struct ldapsam_privates *)methods->private_data;
2896         char *dn;
2897         LDAPMessage *result = NULL;
2898         LDAPMessage *entry = NULL;
2899         int count;
2900         LDAPMod **mods = NULL;
2901         int rc;
2902
2903         pstring filter;
2904
2905         pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
2906                      LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
2907                      get_attr_key2string(groupmap_attr_list,
2908                                          LDAP_ATTR_GROUP_SID),
2909                      sid_string_static(alias));
2910
2911         if (ldapsam_search_one_group(ldap_state, filter,
2912                                      &result) != LDAP_SUCCESS)
2913                 return NT_STATUS_NO_SUCH_ALIAS;
2914
2915         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
2916                                    result);
2917
2918         if (count < 1) {
2919                 DEBUG(4, ("ldapsam_modify_aliasmem: Did not find alias\n"));
2920                 ldap_msgfree(result);
2921                 return NT_STATUS_NO_SUCH_ALIAS;
2922         }
2923
2924         if (count > 1) {
2925                 DEBUG(1, ("ldapsam_modify_aliasmem: Duplicate entries for filter %s: "
2926                           "count=%d\n", filter, count));
2927                 ldap_msgfree(result);
2928                 return NT_STATUS_NO_SUCH_ALIAS;
2929         }
2930
2931         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
2932                                  result);
2933
2934         if (!entry) {
2935                 ldap_msgfree(result);
2936                 return NT_STATUS_UNSUCCESSFUL;
2937         }
2938
2939         dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
2940         if (!dn) {
2941                 ldap_msgfree(result);
2942                 return NT_STATUS_UNSUCCESSFUL;
2943         }
2944
2945         smbldap_set_mod(&mods, modop,
2946                         get_attr_key2string(groupmap_attr_list,
2947                                             LDAP_ATTR_SID_LIST),
2948                         sid_string_static(member));
2949
2950         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
2951
2952         ldap_mods_free(mods, True);
2953         ldap_msgfree(result);
2954
2955         if (rc != LDAP_SUCCESS) {
2956                 char *ld_error = NULL;
2957                 ldap_get_option(ldap_state->smbldap_state->ldap_struct,
2958                                 LDAP_OPT_ERROR_STRING,&ld_error);
2959                 
2960                 DEBUG(0, ("ldapsam_modify_aliasmem: Could not modify alias "
2961                           "for %s, error: %s (%s)\n", dn, ldap_err2string(rc),
2962                           ld_error?ld_error:"unknown"));
2963                 SAFE_FREE(ld_error);
2964                 SAFE_FREE(dn);
2965                 return NT_STATUS_UNSUCCESSFUL;
2966         }
2967
2968         SAFE_FREE(dn);
2969
2970         return NT_STATUS_OK;
2971 }
2972
2973 static NTSTATUS ldapsam_add_aliasmem(struct pdb_methods *methods,
2974                                      const DOM_SID *alias,
2975                                      const DOM_SID *member)
2976 {
2977         return ldapsam_modify_aliasmem(methods, alias, member, LDAP_MOD_ADD);
2978 }
2979
2980 static NTSTATUS ldapsam_del_aliasmem(struct pdb_methods *methods,
2981                                      const DOM_SID *alias,
2982                                      const DOM_SID *member)
2983 {
2984         return ldapsam_modify_aliasmem(methods, alias, member,
2985                                        LDAP_MOD_DELETE);
2986 }
2987
2988 static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
2989                                       const DOM_SID *alias, DOM_SID **members,
2990                                       int *num_members)
2991 {
2992         struct ldapsam_privates *ldap_state =
2993                 (struct ldapsam_privates *)methods->private_data;
2994         LDAPMessage *result = NULL;
2995         LDAPMessage *entry = NULL;
2996         int count;
2997         char **values;
2998         int i;
2999         pstring filter;
3000
3001         *members = NULL;
3002         *num_members = 0;
3003
3004         pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
3005                      LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
3006                      get_attr_key2string(groupmap_attr_list,
3007                                          LDAP_ATTR_GROUP_SID),
3008                      sid_string_static(alias));
3009
3010         if (ldapsam_search_one_group(ldap_state, filter,
3011                                      &result) != LDAP_SUCCESS)
3012                 return NT_STATUS_NO_SUCH_ALIAS;
3013
3014         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
3015                                    result);
3016
3017         if (count < 1) {
3018                 DEBUG(4, ("ldapsam_enum_aliasmem: Did not find alias\n"));
3019                 ldap_msgfree(result);
3020                 return NT_STATUS_NO_SUCH_ALIAS;
3021         }
3022
3023         if (count > 1) {
3024                 DEBUG(1, ("ldapsam_enum_aliasmem: Duplicate entries for filter %s: "
3025                           "count=%d\n", filter, count));
3026                 ldap_msgfree(result);
3027                 return NT_STATUS_NO_SUCH_ALIAS;
3028         }
3029
3030         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
3031                                  result);
3032
3033         if (!entry) {
3034                 ldap_msgfree(result);
3035                 return NT_STATUS_UNSUCCESSFUL;
3036         }
3037
3038         values = ldap_get_values(ldap_state->smbldap_state->ldap_struct,
3039                                  entry,
3040                                  get_attr_key2string(groupmap_attr_list,
3041                                                      LDAP_ATTR_SID_LIST));
3042
3043         if (values == NULL) {
3044                 ldap_msgfree(result);
3045                 return NT_STATUS_OK;
3046         }
3047
3048         count = ldap_count_values(values);
3049
3050         for (i=0; i<count; i++) {
3051                 DOM_SID member;
3052
3053                 if (!string_to_sid(&member, values[i]))
3054                         continue;
3055
3056                 add_sid_to_array(NULL, &member, members, num_members);
3057         }
3058
3059         ldap_value_free(values);
3060         ldap_msgfree(result);
3061
3062         return NT_STATUS_OK;
3063 }
3064
3065 static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
3066                                           TALLOC_CTX *mem_ctx,
3067                                           const DOM_SID *domain_sid,
3068                                           const DOM_SID *members,
3069                                           int num_members,
3070                                           uint32 **alias_rids,
3071                                           int *num_alias_rids)
3072 {
3073         struct ldapsam_privates *ldap_state =
3074                 (struct ldapsam_privates *)methods->private_data;
3075         LDAP *ldap_struct;
3076
3077         const char *attrs[] = { LDAP_ATTRIBUTE_SID, NULL };
3078
3079         LDAPMessage *result = NULL;
3080         LDAPMessage *entry = NULL;
3081         int i;
3082         int rc;
3083         char *filter;
3084
3085         /* This query could be further optimized by adding a
3086            (&(sambaSID=<domain-sid>*)) so that only those aliases that are
3087            asked for in the getuseraliases are returned. */        
3088
3089         filter = talloc_asprintf(mem_ctx,
3090                                  "(&(|(objectclass=%s)(objectclass=%s))(|",
3091                                  LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY);
3092
3093         for (i=0; i<num_members; i++)
3094                 filter = talloc_asprintf(mem_ctx, "%s(sambaSIDList=%s)",
3095                                          filter,
3096                                          sid_string_static(&members[i]));
3097
3098         filter = talloc_asprintf(mem_ctx, "%s))", filter);
3099
3100         rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
3101                             LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
3102
3103         talloc_destroy(mem_ctx);
3104
3105         if (rc != LDAP_SUCCESS)
3106                 return NT_STATUS_UNSUCCESSFUL;
3107
3108         ldap_struct = ldap_state->smbldap_state->ldap_struct;
3109
3110         for (entry = ldap_first_entry(ldap_struct, result);
3111              entry != NULL;
3112              entry = ldap_next_entry(ldap_struct, entry))
3113         {
3114                 fstring sid_str;
3115                 DOM_SID sid;
3116                 uint32 rid;
3117
3118                 if (!smbldap_get_single_attribute(ldap_struct, entry,
3119                                                   LDAP_ATTRIBUTE_SID,
3120                                                   sid_str,
3121                                                   sizeof(sid_str)-1))
3122                         continue;
3123
3124                 if (!string_to_sid(&sid, sid_str))
3125                         continue;
3126
3127                 if (!sid_peek_check_rid(domain_sid, &sid, &rid))
3128                         continue;
3129
3130                 add_rid_to_array_unique(mem_ctx, rid, alias_rids,
3131                                         num_alias_rids);
3132         }
3133
3134         ldap_msgfree(result);
3135         return NT_STATUS_OK;
3136 }
3137
3138 static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
3139                                     TALLOC_CTX *mem_ctx,
3140                                     const DOM_SID *domain_sid,
3141                                     int num_rids,
3142                                     uint32 *rids,
3143                                     const char ***names,
3144                                     uint32 **attrs)
3145 {
3146         struct ldapsam_privates *ldap_state =
3147                 (struct ldapsam_privates *)methods->private_data;
3148         LDAP *ldap_struct = ldap_state->smbldap_state->ldap_struct;
3149         LDAPMessage *msg = NULL;
3150         LDAPMessage *entry;
3151         char *allsids = NULL;
3152         char *tmp;
3153         int i, rc, num_mapped;
3154         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
3155
3156         if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
3157                 return pdb_default_lookup_rids(methods, mem_ctx, domain_sid,
3158                                                num_rids, rids, names, attrs);
3159
3160         if (!sid_equal(domain_sid, get_global_sam_sid())) {
3161                 /* TODO: Sooner or later we need to look up BUILTIN rids as
3162                  * well. -- vl */
3163                 goto done;
3164         }
3165
3166         (*names) = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
3167         (*attrs) = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
3168
3169         if ((num_rids != 0) && (((*names) == NULL) || ((*attrs) == NULL)))
3170                 return NT_STATUS_NO_MEMORY;
3171
3172         for (i=0; i<num_rids; i++)
3173                 (*attrs)[i] = SID_NAME_UNKNOWN;
3174
3175         allsids = strdup("");
3176         if (allsids == NULL) return NT_STATUS_NO_MEMORY;
3177
3178         for (i=0; i<num_rids; i++) {
3179                 DOM_SID sid;
3180                 sid_copy(&sid, domain_sid);
3181                 sid_append_rid(&sid, rids[i]);
3182                 tmp = allsids;
3183                 asprintf(&allsids, "%s(sambaSid=%s)", allsids,
3184                          sid_string_static(&sid));
3185                 if (allsids == NULL) return NT_STATUS_NO_MEMORY;
3186                 free(tmp);
3187         }
3188
3189         /* First look for users */
3190
3191         {
3192                 char *filter;
3193                 const char *ldap_attrs[] = { "uid", "sambaSid", NULL };
3194
3195                 asprintf(&filter, ("(&(objectClass=sambaSamAccount)(|%s))"),
3196                          allsids);
3197                 if (filter == NULL) return NT_STATUS_NO_MEMORY;
3198
3199                 rc = smbldap_search(ldap_state->smbldap_state,
3200                                     lp_ldap_user_suffix(),
3201                                     LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
3202                                     &msg);
3203
3204                 SAFE_FREE(filter);
3205         }
3206
3207         if (rc != LDAP_SUCCESS)
3208                 goto done;
3209
3210         num_mapped = 0;
3211
3212         for (entry = ldap_first_entry(ldap_struct, msg);
3213              entry != NULL;
3214              entry = ldap_next_entry(ldap_struct, entry))
3215         {
3216                 uint32 rid;
3217                 int rid_index;
3218                 fstring str;
3219
3220                 if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
3221                                                     get_global_sam_sid(),
3222                                                     &rid)) {
3223                         DEBUG(2, ("Could not find sid from ldap entry\n"));
3224                         continue;
3225                 }
3226
3227                 if (!smbldap_get_single_attribute(ldap_struct, entry,
3228                                                   "uid", str, sizeof(str)-1)) {
3229                         DEBUG(2, ("Could not retrieve uid attribute\n"));
3230                         continue;
3231                 }
3232
3233                 for (rid_index = 0; rid_index < num_rids; rid_index++) {
3234                         if (rid == rids[rid_index])
3235                                 break;
3236                 }
3237
3238                 if (rid_index == num_rids) {
3239                         DEBUG(2, ("Got a RID not asked for: %d\n", rid));
3240                         continue;
3241                 }
3242
3243                 (*attrs)[rid_index] = SID_NAME_USER;
3244                 (*names)[rid_index] = talloc_strdup(mem_ctx, str);
3245                 if ((*names)[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
3246
3247                 num_mapped += 1;
3248         }
3249
3250         if (num_mapped == num_rids) {
3251                 /* No need to look for groups anymore -- we're done */
3252                 result = NT_STATUS_OK;
3253                 goto done;
3254         }
3255
3256         /* Same game for groups */
3257
3258         {
3259                 char *filter;
3260                 const char *ldap_attrs[] = { "cn", "sambaSid", NULL };
3261
3262                 asprintf(&filter, ("(&(objectClass=sambaGroupMapping)(|%s))"),
3263                          allsids);
3264                 if (filter == NULL) return NT_STATUS_NO_MEMORY;
3265
3266                 rc = smbldap_search(ldap_state->smbldap_state,
3267                                     lp_ldap_group_suffix(),
3268                                     LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
3269                                     &msg);
3270
3271                 SAFE_FREE(filter);
3272         }
3273
3274         if (rc != LDAP_SUCCESS)
3275                 goto done;
3276
3277         for (entry = ldap_first_entry(ldap_struct, msg);
3278              entry != NULL;
3279              entry = ldap_next_entry(ldap_struct, entry))
3280         {
3281                 uint32 rid;
3282                 int rid_index;
3283                 fstring str;
3284
3285                 if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
3286                                                     get_global_sam_sid(),
3287                                                     &rid)) {
3288                         DEBUG(2, ("Could not find sid from ldap entry\n"));
3289                         continue;
3290                 }
3291
3292                 if (!smbldap_get_single_attribute(ldap_struct, entry,
3293                                                   "cn", str, sizeof(str)-1)) {
3294                         DEBUG(2, ("Could not retrieve cn attribute\n"));
3295                         continue;
3296                 }
3297
3298                 for (rid_index = 0; rid_index < num_rids; rid_index++) {
3299                         if (rid == rids[rid_index])
3300                                 break;
3301                 }
3302
3303                 if (rid_index == num_rids) {
3304                         DEBUG(2, ("Got a RID not asked for: %d\n", rid));
3305                         continue;
3306                 }
3307
3308                 (*attrs)[rid_index] = SID_NAME_DOM_GRP;
3309                 (*names)[rid_index] = talloc_strdup(mem_ctx, str);
3310                 if ((*names)[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
3311                 num_mapped += 1;
3312         }
3313
3314         result = NT_STATUS_NONE_MAPPED;
3315
3316         if (num_mapped > 0)
3317                 result = (num_mapped == num_rids) ?
3318                         NT_STATUS_OK : STATUS_SOME_UNMAPPED;
3319  done:
3320         SAFE_FREE(allsids);
3321
3322         if (msg != NULL)
3323                 ldap_msgfree(msg);
3324
3325         return result;
3326 }
3327
3328 /**********************************************************************
3329  Housekeeping
3330  *********************************************************************/
3331
3332 static void free_private_data(void **vp) 
3333 {
3334         struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
3335
3336         smbldap_free_struct(&(*ldap_state)->smbldap_state);
3337
3338         if ((*ldap_state)->result != NULL) {
3339                 ldap_msgfree((*ldap_state)->result);
3340                 (*ldap_state)->result = NULL;
3341         }
3342         if ((*ldap_state)->domain_dn != NULL) {
3343                 SAFE_FREE((*ldap_state)->domain_dn);
3344         }
3345
3346         *ldap_state = NULL;
3347
3348         /* No need to free any further, as it is talloc()ed */
3349 }
3350
3351 /**********************************************************************
3352  Intitalise the parts of the pdb_context that are common to all pdb_ldap modes
3353  *********************************************************************/
3354
3355 static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, 
3356                                         const char *location)
3357 {
3358         NTSTATUS nt_status;
3359         struct ldapsam_privates *ldap_state;
3360
3361         if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
3362                 return nt_status;
3363         }
3364
3365         (*pdb_method)->name = "ldapsam";
3366
3367         (*pdb_method)->setsampwent = ldapsam_setsampwent;
3368         (*pdb_method)->endsampwent = ldapsam_endsampwent;
3369         (*pdb_method)->getsampwent = ldapsam_getsampwent;
3370         (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
3371         (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
3372         (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
3373         (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
3374         (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
3375
3376         (*pdb_method)->getgrsid = ldapsam_getgrsid;
3377         (*pdb_method)->getgrgid = ldapsam_getgrgid;
3378         (*pdb_method)->getgrnam = ldapsam_getgrnam;
3379         (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
3380         (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
3381         (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
3382         (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
3383         (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
3384         (*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships;
3385         (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
3386
3387         /* TODO: Setup private data and free */
3388
3389         ldap_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct ldapsam_privates);
3390         if (!ldap_state) {
3391                 DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n"));
3392                 return NT_STATUS_NO_MEMORY;
3393         }
3394
3395         if (!NT_STATUS_IS_OK(nt_status = 
3396                              smbldap_init(pdb_context->mem_ctx, location, 
3397                                           &ldap_state->smbldap_state)));
3398
3399         ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
3400         if (!ldap_state->domain_name) {
3401                 return NT_STATUS_NO_MEMORY;
3402         }
3403
3404         (*pdb_method)->private_data = ldap_state;
3405
3406         (*pdb_method)->free_private_data = free_private_data;
3407
3408         return NT_STATUS_OK;
3409 }
3410
3411 /**********************************************************************
3412  Initialise the 'compat' mode for pdb_ldap
3413  *********************************************************************/
3414
3415 NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3416 {
3417         NTSTATUS nt_status;
3418         struct ldapsam_privates *ldap_state;
3419
3420 #ifdef WITH_LDAP_SAMCONFIG
3421         if (!location) {
3422                 int ldap_port = lp_ldap_port();
3423                         
3424                 /* remap default port if not using SSL (ie clear or TLS) */
3425                 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
3426                         ldap_port = 389;
3427                 }
3428
3429                 location = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
3430                 if (!location) {
3431                         return NT_STATUS_NO_MEMORY;
3432                 }
3433         }
3434 #endif
3435
3436         if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
3437                 return nt_status;
3438         }
3439
3440         (*pdb_method)->name = "ldapsam_compat";
3441
3442         ldap_state = (*pdb_method)->private_data;
3443         ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
3444
3445         sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
3446
3447         return NT_STATUS_OK;
3448 }
3449
3450 /**********************************************************************
3451  Initialise the normal mode for pdb_ldap
3452  *********************************************************************/
3453
3454 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3455 {
3456         NTSTATUS nt_status;
3457         struct ldapsam_privates *ldap_state;
3458         uint32 alg_rid_base;
3459         pstring alg_rid_base_string;
3460         LDAPMessage *result = NULL;
3461         LDAPMessage *entry = NULL;
3462         DOM_SID ldap_domain_sid;
3463         DOM_SID secrets_domain_sid;
3464         pstring domain_sid_string;
3465         char *dn;
3466
3467         if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
3468                 return nt_status;
3469         }
3470
3471         (*pdb_method)->name = "ldapsam";
3472
3473         (*pdb_method)->add_aliasmem = ldapsam_add_aliasmem;
3474         (*pdb_method)->del_aliasmem = ldapsam_del_aliasmem;
3475         (*pdb_method)->enum_aliasmem = ldapsam_enum_aliasmem;
3476         (*pdb_method)->enum_alias_memberships = ldapsam_alias_memberships;
3477
3478         ldap_state = (*pdb_method)->private_data;
3479         ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
3480
3481         /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
3482         
3483         nt_status = smbldap_search_domain_info(ldap_state->smbldap_state, &result, 
3484                                                ldap_state->domain_name, True);
3485         
3486         if ( !NT_STATUS_IS_OK(nt_status) ) {
3487                 DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain info, nor add one to the domain\n"));
3488                 DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, will be unable to allocate new users/groups, \
3489 and will risk BDCs having inconsistant SIDs\n"));
3490                 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
3491                 return NT_STATUS_OK;
3492         }
3493
3494         /* Given that the above might fail, everything below this must be optional */
3495         
3496         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
3497         if (!entry) {
3498                 DEBUG(0, ("pdb_init_ldapsam: Could not get domain info entry\n"));
3499                 ldap_msgfree(result);
3500                 return NT_STATUS_UNSUCCESSFUL;
3501         }
3502
3503         dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
3504         if (!dn) {
3505                 return NT_STATUS_UNSUCCESSFUL;
3506         }
3507
3508         ldap_state->domain_dn = smb_xstrdup(dn);
3509         ldap_memfree(dn);
3510
3511         if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
3512                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), 
3513                                  domain_sid_string)) {
3514                 BOOL found_sid;
3515                 if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
3516                         DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be read as a valid SID\n", domain_sid_string));
3517                         return NT_STATUS_INVALID_PARAMETER;
3518                 }
3519                 found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid);
3520                 if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) {
3521                         fstring new_sid_str, old_sid_str;
3522                         DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain %s based on pdb_ldap results %s -> %s\n",
3523                                   ldap_state->domain_name, 
3524                                   sid_to_string(old_sid_str, &secrets_domain_sid),
3525                                   sid_to_string(new_sid_str, &ldap_domain_sid)));
3526                         
3527                         /* reset secrets.tdb sid */
3528                         secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid);
3529                         DEBUG(1, ("New global sam SID: %s\n", sid_to_string(new_sid_str, get_global_sam_sid())));
3530                 }
3531                 sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
3532         }
3533
3534         if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
3535                                  get_attr_key2string( dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE ),
3536                                  alg_rid_base_string)) {
3537                 alg_rid_base = (uint32)atol(alg_rid_base_string);
3538                 if (alg_rid_base != algorithmic_rid_base()) {
3539                         DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n"
3540                                   "database was initialised.  Aborting. \n"));
3541                         ldap_msgfree(result);
3542                         return NT_STATUS_UNSUCCESSFUL;
3543                 }
3544         }
3545         ldap_msgfree(result);
3546
3547         return NT_STATUS_OK;
3548 }
3549
3550 NTSTATUS pdb_ldap_init(void)
3551 {
3552         NTSTATUS nt_status;
3553         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
3554                 return nt_status;
3555
3556         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
3557                 return nt_status;
3558
3559         /* Let pdb_nds register backends */
3560         pdb_nds_init();
3561
3562         return NT_STATUS_OK;
3563 }