]> git.samba.org - ira/wip.git/blob - source3/passdb/pdb_ldap.c
Try to remove the last vestiges of unknown_3...
[ira/wip.git] / source3 / passdb / pdb_ldap.c
1 /* 
2    Unix SMB/CIFS mplementation.
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 #undef DBGC_CLASS
49 #define DBGC_CLASS DBGC_PASSDB
50
51 #include <lber.h>
52 #include <ldap.h>
53
54 /*
55  * Work around versions of the LDAP client libs that don't have the OIDs
56  * defined, or have them defined under the old name.  
57  * This functionality is really a factor of the server, not the client 
58  *
59  */
60
61 #if defined(LDAP_EXOP_X_MODIFY_PASSWD) && !defined(LDAP_EXOP_MODIFY_PASSWD)
62 #define LDAP_EXOP_MODIFY_PASSWD LDAP_EXOP_X_MODIFY_PASSWD
63 #elif !defined(LDAP_EXOP_MODIFY_PASSWD)
64 #define LDAP_EXOP_MODIFY_PASSWD "1.3.6.1.4.1.4203.1.11.1"
65 #endif
66
67 #if defined(LDAP_EXOP_X_MODIFY_PASSWD_ID) && !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
68 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID LDAP_EXOP_X_MODIFY_PASSWD_ID
69 #elif !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
70 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID        ((ber_tag_t) 0x80U)
71 #endif
72
73 #if defined(LDAP_EXOP_X_MODIFY_PASSWD_NEW) && !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
74 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW LDAP_EXOP_X_MODIFY_PASSWD_NEW
75 #elif !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
76 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW       ((ber_tag_t) 0x82U)
77 #endif
78
79
80 #ifndef SAM_ACCOUNT
81 #define SAM_ACCOUNT struct sam_passwd
82 #endif
83
84 #include "smbldap.h"
85
86 struct ldapsam_privates {
87         struct smbldap_state *smbldap_state;
88
89         /* Former statics */
90         LDAPMessage *result;
91         LDAPMessage *entry;
92         int index;
93         
94         const char *domain_name;
95         DOM_SID domain_sid;
96         
97         /* configuration items */
98         int schema_ver;
99 };
100
101 /**********************************************************************
102  Free a LDAPMessage (one is stored on the SAM_ACCOUNT).
103  **********************************************************************/
104  
105 static void private_data_free_fn(void **result) 
106 {
107         ldap_msgfree(*result);
108         *result = NULL;
109 }
110
111 /**********************************************************************
112  Get the attribute name given a user schame version.
113  **********************************************************************/
114  
115 static const char* get_userattr_key2string( int schema_ver, int key )
116 {
117         switch ( schema_ver ) {
118                 case SCHEMAVER_SAMBAACCOUNT:
119                         return get_attr_key2string( attrib_map_v22, key );
120                         
121                 case SCHEMAVER_SAMBASAMACCOUNT:
122                         return get_attr_key2string( attrib_map_v30, key );
123                         
124                 default:
125                         DEBUG(0,("get_userattr_key2string: unknown schema version specified\n"));
126                         break;
127         }
128         return NULL;
129 }
130
131 /**********************************************************************
132  Return the list of attribute names given a user schema version.
133 **********************************************************************/
134
135 static char** get_userattr_list( int schema_ver )
136 {
137         switch ( schema_ver ) {
138                 case SCHEMAVER_SAMBAACCOUNT:
139                         return get_attr_list( attrib_map_v22 );
140                         
141                 case SCHEMAVER_SAMBASAMACCOUNT:
142                         return get_attr_list( attrib_map_v30 );
143                 default:
144                         DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
145                         break;
146         }
147         
148         return NULL;
149 }
150
151 /*******************************************************************
152  Generate the LDAP search filter for the objectclass based on the 
153  version of the schema we are using.
154 ******************************************************************/
155
156 static const char* get_objclass_filter( int schema_ver )
157 {
158         static fstring objclass_filter;
159         
160         switch( schema_ver ) {
161                 case SCHEMAVER_SAMBAACCOUNT:
162                         fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT );
163                         break;
164                 case SCHEMAVER_SAMBASAMACCOUNT:
165                         fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT );
166                         break;
167                 default:
168                         DEBUG(0,("get_objclass_filter: Invalid schema version specified!\n"));
169                         break;
170         }
171         
172         return objclass_filter; 
173 }
174
175 /*******************************************************************
176  Run the search by name.
177 ******************************************************************/
178
179 static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, 
180                                           const char *user,
181                                           LDAPMessage ** result, char **attr)
182 {
183         pstring filter;
184         char *escape_user = escape_ldap_string_alloc(user);
185
186         if (!escape_user) {
187                 return LDAP_NO_MEMORY;
188         }
189
190         /*
191          * in the filter expression, replace %u with the real name
192          * so in ldap filter, %u MUST exist :-)
193          */
194         pstr_sprintf(filter, "(&%s%s)", lp_ldap_filter(), 
195                 get_objclass_filter(ldap_state->schema_ver));
196
197         /* 
198          * have to use this here because $ is filtered out
199            * in pstring_sub
200          */
201         
202
203         all_string_sub(filter, "%u", escape_user, sizeof(pstring));
204         SAFE_FREE(escape_user);
205
206         return smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result);
207 }
208
209 /*******************************************************************
210  Run the search by rid.
211 ******************************************************************/
212
213 static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, 
214                                          uint32 rid, LDAPMessage ** result, 
215                                          char **attr)
216 {
217         pstring filter;
218         int rc;
219
220         pstr_sprintf(filter, "(&(rid=%i)%s)", rid, 
221                 get_objclass_filter(ldap_state->schema_ver));
222         
223         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result);
224         
225         return rc;
226 }
227
228 /*******************************************************************
229  Run the search by SID.
230 ******************************************************************/
231
232 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, 
233                                          const DOM_SID *sid, LDAPMessage ** result, 
234                                          char **attr)
235 {
236         pstring filter;
237         int rc;
238         fstring sid_string;
239
240         pstr_sprintf(filter, "(&(%s=%s)%s)", 
241                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
242                 sid_to_string(sid_string, sid), 
243                 get_objclass_filter(ldap_state->schema_ver));
244                 
245         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result);
246         
247         return rc;
248 }
249
250 /*******************************************************************
251  Delete complete object or objectclass and attrs from
252  object found in search_result depending on lp_ldap_delete_dn
253 ******************************************************************/
254
255 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
256                                      LDAPMessage *result,
257                                      const char *objectclass,
258                                      char **attrs)
259 {
260         int rc;
261         LDAPMessage *entry = NULL;
262         LDAPMod **mods = NULL;
263         char *name, *dn;
264         BerElement *ptr = NULL;
265
266         rc = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
267
268         if (rc != 1) {
269                 DEBUG(0, ("ldapsam_delete_entry: Entry must exist exactly once!\n"));
270                 return NT_STATUS_UNSUCCESSFUL;
271         }
272
273         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
274         dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
275         if (!dn) {
276                 return NT_STATUS_UNSUCCESSFUL;
277         }
278
279         if (lp_ldap_delete_dn()) {
280                 NTSTATUS ret = NT_STATUS_OK;
281                 rc = smbldap_delete(ldap_state->smbldap_state, dn);
282
283                 if (rc != LDAP_SUCCESS) {
284                         DEBUG(0, ("ldapsam_delete_entry: Could not delete object %s\n", dn));
285                         ret = NT_STATUS_UNSUCCESSFUL;
286                 }
287                 SAFE_FREE(dn);
288                 return ret;
289         }
290
291         /* Ok, delete only the SAM attributes */
292         
293         for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr);
294              name != NULL;
295              name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) {
296                 char **attrib;
297
298                 /* We are only allowed to delete the attributes that
299                    really exist. */
300
301                 for (attrib = attrs; *attrib != NULL; attrib++) {
302                         if (StrCaseCmp(*attrib, name) == 0) {
303                                 DEBUG(10, ("ldapsam_delete_entry: deleting attribute %s\n", name));
304                                 smbldap_set_mod(&mods, LDAP_MOD_DELETE, name, NULL);
305                         }
306                 }
307
308                 ldap_memfree(name);
309         }
310         
311         if (ptr != NULL) {
312                 ber_free(ptr, 0);
313         }
314         
315         smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
316
317         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
318         ldap_mods_free(mods, True);
319
320         if (rc != LDAP_SUCCESS) {
321                 char *ld_error = NULL;
322                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
323                                 &ld_error);
324                 
325                 DEBUG(0, ("ldapsam_delete_entry: Could not delete attributes for %s, error: %s (%s)\n",
326                           dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
327                 SAFE_FREE(ld_error);
328                 SAFE_FREE(dn);
329                 return NT_STATUS_UNSUCCESSFUL;
330         }
331
332         SAFE_FREE(dn);
333         return NT_STATUS_OK;
334 }
335                   
336 /* New Interface is being implemented here */
337
338 #if 0   /* JERRY - not uesed anymore */
339
340 /**********************************************************************
341 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
342 *********************************************************************/
343 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, 
344                                 SAM_ACCOUNT * sampass,
345                                 LDAPMessage * entry,
346                                 gid_t *gid)
347 {
348         pstring  homedir;
349         pstring  temp;
350         char **ldap_values;
351         char **values;
352
353         if ((ldap_values = ldap_get_values (ldap_state->smbldap_state->ldap_struct, entry, "objectClass")) == NULL) {
354                 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
355                 return False;
356         }
357
358         for (values=ldap_values;*values;values++) {
359                 if (strequal(*values, LDAP_OBJ_POSIXACCOUNT )) {
360                         break;
361                 }
362         }
363         
364         if (!*values) { /*end of array, no posixAccount */
365                 DEBUG(10, ("user does not have %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
366                 ldap_value_free(ldap_values);
367                 return False;
368         }
369         ldap_value_free(ldap_values);
370
371         if ( !smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
372                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_UNIX_HOME), homedir) ) 
373         {
374                 return False;
375         }
376         
377         if ( !smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
378                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_GIDNUMBER), temp) )
379         {
380                 return False;
381         }
382         
383         *gid = (gid_t)atol(temp);
384
385         pdb_set_unix_homedir(sampass, homedir, PDB_SET);
386         
387         DEBUG(10, ("user has %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
388         
389         return True;
390 }
391
392 #endif
393
394 /**********************************************************************
395  Initialize SAM_ACCOUNT from an LDAP query.
396  (Based on init_sam_from_buffer in pdb_tdb.c)
397 *********************************************************************/
398
399 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, 
400                                 SAM_ACCOUNT * sampass,
401                                 LDAPMessage * entry)
402 {
403         time_t  logon_time,
404                         logoff_time,
405                         kickoff_time,
406                         pass_last_set_time, 
407                         pass_can_change_time, 
408                         pass_must_change_time;
409         pstring         username, 
410                         domain,
411                         nt_username,
412                         fullname,
413                         homedir,
414                         dir_drive,
415                         logon_script,
416                         profile_path,
417                         acct_desc,
418                         workstations;
419         char            munged_dial[2048];
420         uint32          user_rid; 
421         uint8           smblmpwd[LM_HASH_LEN],
422                         smbntpwd[NT_HASH_LEN];
423         uint16          acct_ctrl = 0, 
424                         logon_divs;
425         uint16          bad_password_count = 0, 
426                         logon_count = 0;
427         uint32 hours_len;
428         uint8           hours[MAX_HOURS_LEN];
429         pstring temp;
430
431         /*
432          * do a little initialization
433          */
434         username[0]     = '\0';
435         domain[0]       = '\0';
436         nt_username[0]  = '\0';
437         fullname[0]     = '\0';
438         homedir[0]      = '\0';
439         dir_drive[0]    = '\0';
440         logon_script[0] = '\0';
441         profile_path[0] = '\0';
442         acct_desc[0]    = '\0';
443         munged_dial[0]  = '\0';
444         workstations[0] = '\0';
445          
446
447         if (sampass == NULL || ldap_state == NULL || entry == NULL) {
448                 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
449                 return False;
450         }
451
452         if (ldap_state->smbldap_state->ldap_struct == NULL) {
453                 DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->ldap_struct is NULL!\n"));
454                 return False;
455         }
456         
457         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) {
458                 DEBUG(1, ("init_sam_from_ldap: No uid attribute found for this user!\n"));
459                 return False;
460         }
461
462         DEBUG(2, ("init_sam_from_ldap: Entry found for user: %s\n", username));
463
464         pstrcpy(nt_username, username);
465
466         pstrcpy(domain, ldap_state->domain_name);
467         
468         pdb_set_username(sampass, username, PDB_SET);
469
470         pdb_set_domain(sampass, domain, PDB_DEFAULT);
471         pdb_set_nt_username(sampass, nt_username, PDB_SET);
472
473         /* deal with different attributes between the schema first */
474         
475         if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ) {
476                 if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
477                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp)) {
478                         pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
479                 }
480                 
481                 if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
482                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp)) {
483                         pdb_set_group_sid_from_string(sampass, temp, PDB_SET);                  
484                 } else {
485                         pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
486                 }
487         } else {
488                 if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
489                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp)) {
490                         user_rid = (uint32)atol(temp);
491                         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
492                 }
493                 
494                 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
495                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp)) {
496                         pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
497                 } else {
498                         uint32 group_rid;
499                         
500                         group_rid = (uint32)atol(temp);
501                         
502                         /* for some reason, we often have 0 as a primary group RID.
503                            Make sure that we treat this just as a 'default' value */
504                            
505                         if ( group_rid > 0 )
506                                 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
507                         else
508                                 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
509                 }
510         }
511
512         if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
513                 DEBUG(1, ("init_sam_from_ldap: no %s or %s attribute found for this user %s\n", 
514                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
515                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID),
516                         username));
517                 return False;
518         }
519
520
521 #if 0   /* JERRY -- not used anymore */
522         /* 
523          * If so configured, try and get the values from LDAP 
524          */
525
526         if (lp_ldap_trust_ids() && (get_unix_attributes(ldap_state, sampass, entry, &gid))) 
527         {       
528                 if (pdb_get_init_flags(sampass,PDB_GROUPSID) == PDB_DEFAULT) 
529                 {
530                         GROUP_MAP map;
531                         /* call the mapping code here */
532                         if(pdb_getgrgid(&map, gid)) {
533                                 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
534                         } 
535                         else {
536                                 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
537                         }
538                 }
539         }
540 #endif
541
542         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
543                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp)) {
544                 /* leave as default */
545         } else {
546                 pass_last_set_time = (time_t) atol(temp);
547                 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
548         }
549
550         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
551                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp)) {
552                 /* leave as default */
553         } else {
554                 logon_time = (time_t) atol(temp);
555                 pdb_set_logon_time(sampass, logon_time, PDB_SET);
556         }
557
558         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
559                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp)) {
560                 /* leave as default */
561         } else {
562                 logoff_time = (time_t) atol(temp);
563                 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
564         }
565
566         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
567                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp)) {
568                 /* leave as default */
569         } else {
570                 kickoff_time = (time_t) atol(temp);
571                 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
572         }
573
574         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
575                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp)) {
576                 /* leave as default */
577         } else {
578                 pass_can_change_time = (time_t) atol(temp);
579                 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
580         }
581
582         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
583                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp)) {    
584                 /* leave as default */
585         } else {
586                 pass_must_change_time = (time_t) atol(temp);
587                 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
588         }
589
590         /* recommend that 'gecos' and 'displayName' should refer to the same
591          * attribute OID.  userFullName depreciated, only used by Samba
592          * primary rules of LDAP: don't make a new attribute when one is already defined
593          * that fits your needs; using cn then displayName rather than 'userFullName'
594          */
595
596         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
597                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), fullname)) {
598                 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
599                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_CN), fullname)) {
600                         /* leave as default */
601                 } else {
602                         pdb_set_fullname(sampass, fullname, PDB_SET);
603                 }
604         } else {
605                 pdb_set_fullname(sampass, fullname, PDB_SET);
606         }
607
608         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
609                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive)) 
610         {
611                 pdb_set_dir_drive( sampass, 
612                         talloc_sub_basic(sampass->mem_ctx, username, lp_logon_drive()),
613                         PDB_DEFAULT );
614         } else {
615                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
616         }
617
618         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
619                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir)) 
620         {
621                 pdb_set_homedir( sampass, 
622                         talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()),
623                         PDB_DEFAULT );
624         } else {
625                 pdb_set_homedir(sampass, homedir, PDB_SET);
626         }
627
628         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
629                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script)) 
630         {
631                 pdb_set_logon_script( sampass, 
632                         talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()), 
633                         PDB_DEFAULT );
634         } else {
635                 pdb_set_logon_script(sampass, logon_script, PDB_SET);
636         }
637
638         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
639                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path)) 
640         {
641                 pdb_set_profile_path( sampass, 
642                         talloc_sub_basic( sampass->mem_ctx, username, lp_logon_path()),
643                         PDB_DEFAULT );
644         } else {
645                 pdb_set_profile_path(sampass, profile_path, PDB_SET);
646         }
647
648         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
649                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), acct_desc)) 
650         {
651                 /* leave as default */
652         } else {
653                 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
654         }
655
656         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
657                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), workstations)) {
658                 /* leave as default */;
659         } else {
660                 pdb_set_workstations(sampass, workstations, PDB_SET);
661         }
662
663         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
664                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MUNGED_DIAL), munged_dial)) {
665                 /* leave as default */;
666         } else {
667                 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
668         }
669         
670         /* FIXME: hours stuff should be cleaner */
671         
672         logon_divs = 168;
673         hours_len = 21;
674         memset(hours, 0xff, hours_len);
675
676         if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, 
677                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) {
678                 /* leave as default */
679         } else {
680                 pdb_gethexpwd(temp, smblmpwd);
681                 memset((char *)temp, '\0', strlen(temp)+1);
682                 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
683                         return False;
684                 ZERO_STRUCT(smblmpwd);
685         }
686
687         if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry,
688                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) {
689                 /* leave as default */
690         } else {
691                 pdb_gethexpwd(temp, smbntpwd);
692                 memset((char *)temp, '\0', strlen(temp)+1);
693                 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
694                         return False;
695                 ZERO_STRUCT(smbntpwd);
696         }
697
698         if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry,
699                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp)) {
700                 acct_ctrl |= ACB_NORMAL;
701         } else {
702                 acct_ctrl = pdb_decode_acct_ctrl(temp);
703
704                 if (acct_ctrl == 0)
705                         acct_ctrl |= ACB_NORMAL;
706
707                 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
708         }
709
710         pdb_set_hours_len(sampass, hours_len, PDB_SET);
711         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
712
713 /*      pdb_set_munged_dial(sampass, munged_dial, PDB_SET); */
714         
715         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
716                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_BAD_PASSWORD_COUNT), temp)) {
717                         /* leave as default */
718         } else {
719                 bad_password_count = (uint32) atol(temp);
720                 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
721         }
722
723         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
724                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_COUNT), temp)) {
725                         /* leave as default */
726         } else {
727                 logon_count = (uint32) atol(temp);
728                 pdb_set_logon_count(sampass, logon_count, PDB_SET);
729         }
730
731         /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
732
733         pdb_set_hours(sampass, hours, PDB_SET);
734
735         return True;
736 }
737
738 /**********************************************************************
739  Initialize SAM_ACCOUNT from an LDAP query.
740  (Based on init_buffer_from_sam in pdb_tdb.c)
741 *********************************************************************/
742
743 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, 
744                                 LDAPMessage *existing,
745                                 LDAPMod *** mods, SAM_ACCOUNT * sampass,
746                                 BOOL (*need_update)(const SAM_ACCOUNT *,
747                                                     enum pdb_elements))
748 {
749         pstring temp;
750         uint32 rid;
751
752         if (mods == NULL || sampass == NULL) {
753                 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
754                 return False;
755         }
756
757         *mods = NULL;
758
759         /* 
760          * took out adding "objectclass: sambaAccount"
761          * do this on a per-mod basis
762          */
763         if (need_update(sampass, PDB_USERNAME))
764                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, 
765                               "uid", pdb_get_username(sampass));
766
767         DEBUG(2, ("init_ldap_from_sam: Setting entry for user: %s\n", pdb_get_username(sampass)));
768
769         /* only update the RID if we actually need to */
770         if (need_update(sampass, PDB_USERSID)) {
771                 fstring sid_string;
772                 fstring dom_sid_string;
773                 const DOM_SID *user_sid = pdb_get_user_sid(sampass);
774                 
775                 switch ( ldap_state->schema_ver ) {
776                         case SCHEMAVER_SAMBAACCOUNT:
777                                 if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) {
778                                         DEBUG(1, ("init_ldap_from_sam: User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", 
779                                                 sid_to_string(sid_string, user_sid), 
780                                                 sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
781                                         return False;
782                                 }
783                                 slprintf(temp, sizeof(temp) - 1, "%i", rid);
784                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
785                                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), 
786                                         temp);
787                                 break;
788                                 
789                         case SCHEMAVER_SAMBASAMACCOUNT:
790                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
791                                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), 
792                                         sid_to_string(sid_string, user_sid));                                 
793                                 break;
794                                 
795                         default:
796                                 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
797                                 break;
798                 }               
799         }
800
801         /* we don't need to store the primary group RID - so leaving it
802            'free' to hang off the unix primary group makes life easier */
803
804         if (need_update(sampass, PDB_GROUPSID)) {
805                 fstring sid_string;
806                 fstring dom_sid_string;
807                 const DOM_SID *group_sid = pdb_get_group_sid(sampass);
808                 
809                 switch ( ldap_state->schema_ver ) {
810                         case SCHEMAVER_SAMBAACCOUNT:
811                                 if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) {
812                                         DEBUG(1, ("init_ldap_from_sam: User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
813                                                 sid_to_string(sid_string, group_sid),
814                                                 sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
815                                         return False;
816                                 }
817
818                                 slprintf(temp, sizeof(temp) - 1, "%i", rid);
819                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
820                                         get_userattr_key2string(ldap_state->schema_ver, 
821                                         LDAP_ATTR_PRIMARY_GROUP_RID), temp);
822                                 break;
823                                 
824                         case SCHEMAVER_SAMBASAMACCOUNT:
825                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
826                                         get_userattr_key2string(ldap_state->schema_ver, 
827                                         LDAP_ATTR_PRIMARY_GROUP_SID), sid_to_string(sid_string, group_sid));
828                                 break;
829                                 
830                         default:
831                                 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
832                                 break;
833                 }
834                 
835         }
836         
837         /* displayName, cn, and gecos should all be the same
838          *  most easily accomplished by giving them the same OID
839          *  gecos isn't set here b/c it should be handled by the 
840          *  add-user script
841          *  We change displayName only and fall back to cn if
842          *  it does not exist.
843          */
844
845         if (need_update(sampass, PDB_FULLNAME))
846                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
847                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), 
848                         pdb_get_fullname(sampass));
849
850         if (need_update(sampass, PDB_ACCTDESC))
851                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
852                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), 
853                         pdb_get_acct_desc(sampass));
854
855         if (need_update(sampass, PDB_WORKSTATIONS))
856                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
857                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), 
858                         pdb_get_workstations(sampass));
859         
860         if (need_update(sampass, PDB_MUNGEDDIAL))
861                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
862                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MUNGED_DIAL), 
863                         pdb_get_munged_dial(sampass));
864         
865         if (need_update(sampass, PDB_SMBHOME))
866                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
867                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), 
868                         pdb_get_homedir(sampass));
869                         
870         if (need_update(sampass, PDB_DRIVE))
871                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
872                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), 
873                         pdb_get_dir_drive(sampass));
874
875         if (need_update(sampass, PDB_LOGONSCRIPT))
876                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
877                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), 
878                         pdb_get_logon_script(sampass));
879
880         if (need_update(sampass, PDB_PROFILE))
881                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
882                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), 
883                         pdb_get_profile_path(sampass));
884
885         slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
886         if (need_update(sampass, PDB_LOGONTIME))
887                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
888                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp);
889
890         slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
891         if (need_update(sampass, PDB_LOGOFFTIME))
892                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
893                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp);
894
895         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
896         if (need_update(sampass, PDB_KICKOFFTIME))
897                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
898                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
899
900         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
901         if (need_update(sampass, PDB_CANCHANGETIME))
902                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
903                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
904
905         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
906         if (need_update(sampass, PDB_MUSTCHANGETIME))
907                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
908                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp);
909
910         if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))
911                         || (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
912
913                 if (need_update(sampass, PDB_LMPASSWD)) {
914                         const uchar *lm_pw =  pdb_get_lanman_passwd(sampass);
915                         if (lm_pw) {
916                                 pdb_sethexpwd(temp, lm_pw,
917                                               pdb_get_acct_ctrl(sampass));
918                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
919                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), 
920                                                  temp);
921                         } else {
922                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
923                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), 
924                                                  NULL);
925                         }
926                 }
927                 if (need_update(sampass, PDB_NTPASSWD)) {
928                         const uchar *nt_pw =  pdb_get_nt_passwd(sampass);
929                         if (nt_pw) {
930                                 pdb_sethexpwd(temp, nt_pw,
931                                               pdb_get_acct_ctrl(sampass));
932                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
933                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), 
934                                                  temp);
935                         } else {
936                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
937                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), 
938                                                  NULL);
939                         }
940                 }
941
942                 if (need_update(sampass, PDB_PASSLASTSET)) {
943                         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
944                         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
945                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), 
946                                 temp);
947                 }
948         }
949
950         /* FIXME: Hours stuff goes in LDAP  */
951
952         if (need_update(sampass, PDB_ACCTCTRL))
953                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
954                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), 
955                         pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), NEW_PW_FORMAT_SPACE_PADDED_LEN));
956
957         return True;
958 }
959
960 /**********************************************************************
961  Connect to LDAP server for password enumeration.
962 *********************************************************************/
963
964 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
965 {
966         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
967         int rc;
968         pstring filter;
969         char **attr_list;
970
971         pstr_sprintf( filter, "(&%s%s)", lp_ldap_filter(), 
972                 get_objclass_filter(ldap_state->schema_ver));
973         all_string_sub(filter, "%u", "*", sizeof(pstring));
974
975         attr_list = get_userattr_list(ldap_state->schema_ver);
976         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, 
977                                    attr_list, &ldap_state->result);
978         free_attr_list( attr_list );
979
980         if (rc != LDAP_SUCCESS) {
981                 DEBUG(0, ("ldapsam_setsampwent: LDAP search failed: %s\n", ldap_err2string(rc)));
982                 DEBUG(3, ("ldapsam_setsampwent: Query was: %s, %s\n", lp_ldap_suffix(), filter));
983                 ldap_msgfree(ldap_state->result);
984                 ldap_state->result = NULL;
985                 return NT_STATUS_UNSUCCESSFUL;
986         }
987
988         DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
989                 ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
990                 ldap_state->result)));
991
992         ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
993                                  ldap_state->result);
994         ldap_state->index = 0;
995
996         return NT_STATUS_OK;
997 }
998
999 /**********************************************************************
1000  End enumeration of the LDAP password list.
1001 *********************************************************************/
1002
1003 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1004 {
1005         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1006         if (ldap_state->result) {
1007                 ldap_msgfree(ldap_state->result);
1008                 ldap_state->result = NULL;
1009         }
1010 }
1011
1012 /**********************************************************************
1013 Get the next entry in the LDAP password database.
1014 *********************************************************************/
1015
1016 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
1017 {
1018         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1019         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1020         BOOL bret = False;
1021
1022         while (!bret) {
1023                 if (!ldap_state->entry)
1024                         return ret;
1025                 
1026                 ldap_state->index++;
1027                 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
1028                 
1029                 ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
1030                                             ldap_state->entry); 
1031         }
1032
1033         return NT_STATUS_OK;
1034 }
1035
1036 /**********************************************************************
1037 Get SAM_ACCOUNT entry from LDAP by username.
1038 *********************************************************************/
1039
1040 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
1041 {
1042         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1043         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1044         LDAPMessage *result = NULL;
1045         LDAPMessage *entry = NULL;
1046         int count;
1047         char ** attr_list;
1048         int rc;
1049         
1050         attr_list = get_userattr_list( ldap_state->schema_ver );
1051         rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
1052         free_attr_list( attr_list );
1053
1054         if ( rc != LDAP_SUCCESS ) 
1055                 return NT_STATUS_NO_SUCH_USER;
1056         
1057         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1058         
1059         if (count < 1) {
1060                 DEBUG(4, ("ldapsam_getsampwnam: Unable to locate user [%s] count=%d\n", sname, count));
1061                 ldap_msgfree(result);
1062                 return NT_STATUS_NO_SUCH_USER;
1063         } else if (count > 1) {
1064                 DEBUG(1, ("ldapsam_getsampwnam: Duplicate entries for this user [%s] Failing. count=%d\n", sname, count));
1065                 ldap_msgfree(result);
1066                 return NT_STATUS_NO_SUCH_USER;
1067         }
1068
1069         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1070         if (entry) {
1071                 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1072                         DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1073                         ldap_msgfree(result);
1074                         return NT_STATUS_NO_SUCH_USER;
1075                 }
1076                 pdb_set_backend_private_data(user, result, 
1077                                              private_data_free_fn, 
1078                                              my_methods, PDB_CHANGED);
1079                 ret = NT_STATUS_OK;
1080         } else {
1081                 ldap_msgfree(result);
1082         }
1083         return ret;
1084 }
1085
1086 static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, 
1087                                    const DOM_SID *sid, LDAPMessage **result) 
1088 {
1089         int rc = -1;
1090         char ** attr_list;
1091         uint32 rid;
1092
1093         switch ( ldap_state->schema_ver ) {
1094                 case SCHEMAVER_SAMBASAMACCOUNT:
1095                         attr_list = get_userattr_list(ldap_state->schema_ver);
1096                         rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list);
1097                         free_attr_list( attr_list );
1098
1099                         if ( rc != LDAP_SUCCESS ) 
1100                                 return rc;
1101                         break;
1102                         
1103                 case SCHEMAVER_SAMBAACCOUNT:
1104                         if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) {
1105                                 return rc;
1106                         }
1107                 
1108                         attr_list = get_userattr_list(ldap_state->schema_ver);
1109                         rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list );
1110                         free_attr_list( attr_list );
1111
1112                         if ( rc != LDAP_SUCCESS ) 
1113                                 return rc;
1114                         break;
1115         }
1116         return rc;
1117 }
1118
1119 /**********************************************************************
1120  Get SAM_ACCOUNT entry from LDAP by SID.
1121 *********************************************************************/
1122
1123 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1124 {
1125         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1126         LDAPMessage *result = NULL;
1127         LDAPMessage *entry = NULL;
1128         int count;
1129         int rc;
1130         fstring sid_string;
1131
1132         rc = ldapsam_get_ldap_user_by_sid(ldap_state, 
1133                                           sid, &result); 
1134         if (rc != LDAP_SUCCESS)
1135                 return NT_STATUS_NO_SUCH_USER;
1136
1137         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1138         
1139         if (count < 1) {
1140                 DEBUG(4, ("ldapsam_getsampwsid: Unable to locate SID [%s] count=%d\n", sid_to_string(sid_string, sid),
1141                        count));
1142                 ldap_msgfree(result);
1143                 return NT_STATUS_NO_SUCH_USER;
1144         }  else if (count > 1) {
1145                 DEBUG(1, ("ldapsam_getsampwsid: More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid),
1146                        count));
1147                 ldap_msgfree(result);
1148                 return NT_STATUS_NO_SUCH_USER;
1149         }
1150
1151         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1152         if (!entry) {
1153                 ldap_msgfree(result);
1154                 return NT_STATUS_NO_SUCH_USER;
1155         }
1156
1157         if (!init_sam_from_ldap(ldap_state, user, entry)) {
1158                 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1159                 ldap_msgfree(result);
1160                 return NT_STATUS_NO_SUCH_USER;
1161         }
1162
1163         pdb_set_backend_private_data(user, result, 
1164                                      private_data_free_fn, 
1165                                      my_methods, PDB_CHANGED);
1166         return NT_STATUS_OK;
1167 }       
1168
1169 /********************************************************************
1170  Do the actual modification - also change a plaintext passord if 
1171  it it set.
1172 **********************************************************************/
1173
1174 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, 
1175                                      SAM_ACCOUNT *newpwd, char *dn,
1176                                      LDAPMod **mods, int ldap_op, 
1177                                      BOOL (*need_update)(const SAM_ACCOUNT *, enum pdb_elements))
1178 {
1179         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1180         int rc;
1181         
1182         if (!my_methods || !newpwd || !dn) {
1183                 return NT_STATUS_INVALID_PARAMETER;
1184         }
1185         
1186         if (!mods) {
1187                 DEBUG(5,("ldapsam_modify_entry: mods is empty: nothing to modify\n"));
1188                 /* may be password change below however */
1189         } else {
1190                 switch(ldap_op) {
1191                         case LDAP_MOD_ADD: 
1192                                 smbldap_set_mod(&mods, LDAP_MOD_ADD, 
1193                                                 "objectclass", 
1194                                                 LDAP_OBJ_ACCOUNT);
1195                                 rc = smbldap_add(ldap_state->smbldap_state, 
1196                                                  dn, mods);
1197                                 break;
1198                         case LDAP_MOD_REPLACE: 
1199                                 rc = smbldap_modify(ldap_state->smbldap_state, 
1200                                                     dn ,mods);
1201                                 break;
1202                         default:        
1203                                 DEBUG(0,("ldapsam_modify_entry: Wrong LDAP operation type: %d!\n", 
1204                                          ldap_op));
1205                                 return NT_STATUS_INVALID_PARAMETER;
1206                 }
1207                 
1208                 if (rc!=LDAP_SUCCESS) {
1209                         char *ld_error = NULL;
1210                         ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1211                                         &ld_error);
1212                         DEBUG(1, ("ldapsam_modify_entry: Failed to %s user dn= %s with: %s\n\t%s\n",
1213                                ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1214                                dn, ldap_err2string(rc),
1215                                ld_error?ld_error:"unknown"));
1216                         SAFE_FREE(ld_error);
1217                         return NT_STATUS_UNSUCCESSFUL;
1218                 }  
1219         }
1220         
1221         if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
1222                         (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
1223                         need_update(newpwd, PDB_PLAINTEXT_PW) &&
1224                         (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1225                 BerElement *ber;
1226                 struct berval *bv;
1227                 char *retoid;
1228                 struct berval *retdata;
1229                 char *utf8_password;
1230                 char *utf8_dn;
1231
1232                 if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
1233                         return NT_STATUS_NO_MEMORY;
1234                 }
1235
1236                 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
1237                         return NT_STATUS_NO_MEMORY;
1238                 }
1239
1240                 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1241                         DEBUG(0,("ber_alloc_t returns NULL\n"));
1242                         SAFE_FREE(utf8_password);
1243                         return NT_STATUS_UNSUCCESSFUL;
1244                 }
1245
1246                 ber_printf (ber, "{");
1247                 ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, utf8_dn);
1248                 ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, utf8_password);
1249                 ber_printf (ber, "N}");
1250
1251                 if ((rc = ber_flatten (ber, &bv))<0) {
1252                         DEBUG(0,("ldapsam_modify_entry: ber_flatten returns a value <0\n"));
1253                         ber_free(ber,1);
1254                         SAFE_FREE(utf8_dn);
1255                         SAFE_FREE(utf8_password);
1256                         return NT_STATUS_UNSUCCESSFUL;
1257                 }
1258                 
1259                 SAFE_FREE(utf8_dn);
1260                 SAFE_FREE(utf8_password);
1261                 ber_free(ber, 1);
1262
1263                 if ((rc = smbldap_extended_operation(ldap_state->smbldap_state, 
1264                                                      LDAP_EXOP_MODIFY_PASSWD,
1265                                                      bv, NULL, NULL, &retoid, 
1266                                                      &retdata)) != LDAP_SUCCESS) {
1267                         char *ld_error = NULL;
1268                         ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1269                                         &ld_error);
1270                         DEBUG(0,("ldapsam_modify_entry: LDAP Password could not be changed for user %s: %s\n\t%s\n",
1271                                 pdb_get_username(newpwd), ldap_err2string(rc), ld_error?ld_error:"unknown"));
1272                         SAFE_FREE(ld_error);
1273                         ber_bvfree(bv);
1274                         return NT_STATUS_UNSUCCESSFUL;
1275                 } else {
1276                         DEBUG(3,("ldapsam_modify_entry: LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1277 #ifdef DEBUG_PASSWORD
1278                         DEBUG(100,("ldapsam_modify_entry: LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
1279 #endif    
1280                         ber_bvfree(retdata);
1281                         ber_memfree(retoid);
1282                 }
1283                 ber_bvfree(bv);
1284         }
1285         return NT_STATUS_OK;
1286 }
1287
1288 /**********************************************************************
1289  Delete entry from LDAP for username.
1290 *********************************************************************/
1291
1292 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1293 {
1294         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1295         const char *sname;
1296         int rc;
1297         LDAPMessage *result = NULL;
1298         NTSTATUS ret;
1299         char **attr_list;
1300         fstring objclass;
1301
1302         if (!sam_acct) {
1303                 DEBUG(0, ("ldapsam_delete_sam_account: sam_acct was NULL!\n"));
1304                 return NT_STATUS_INVALID_PARAMETER;
1305         }
1306
1307         sname = pdb_get_username(sam_acct);
1308
1309         DEBUG (3, ("ldapsam_delete_sam_account: Deleting user %s from LDAP.\n", sname));
1310
1311         attr_list= get_userattr_list( ldap_state->schema_ver );
1312         rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
1313
1314         if (rc != LDAP_SUCCESS)  {
1315                 free_attr_list( attr_list );
1316                 return NT_STATUS_NO_SUCH_USER;
1317         }
1318         
1319         switch ( ldap_state->schema_ver ) {
1320                 case SCHEMAVER_SAMBASAMACCOUNT:
1321                         fstrcpy( objclass, LDAP_OBJ_SAMBASAMACCOUNT );
1322                         break;
1323                         
1324                 case SCHEMAVER_SAMBAACCOUNT:
1325                         fstrcpy( objclass, LDAP_OBJ_SAMBAACCOUNT );
1326                         break;
1327                 default:
1328                         fstrcpy( objclass, "UNKNOWN" );
1329                         DEBUG(0,("ldapsam_delete_sam_account: Unknown schema version specified!\n"));
1330                                 break;
1331         }
1332
1333         ret = ldapsam_delete_entry(ldap_state, result, objclass, attr_list );
1334         ldap_msgfree(result);
1335         free_attr_list( attr_list );
1336
1337         return ret;
1338 }
1339
1340 /**********************************************************************
1341  Helper function to determine for update_sam_account whether
1342  we need LDAP modification.
1343 *********************************************************************/
1344
1345 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
1346                                enum pdb_elements element)
1347 {
1348         return IS_SAM_CHANGED(sampass, element);
1349 }
1350
1351 /**********************************************************************
1352  Update SAM_ACCOUNT.
1353 *********************************************************************/
1354
1355 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1356 {
1357         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1358         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1359         int rc = 0;
1360         char *dn;
1361         LDAPMessage *result = NULL;
1362         LDAPMessage *entry = NULL;
1363         LDAPMod **mods = NULL;
1364         char **attr_list;
1365
1366         result = pdb_get_backend_private_data(newpwd, my_methods);
1367         if (!result) {
1368                 attr_list = get_userattr_list(ldap_state->schema_ver);
1369                 rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list );
1370                 free_attr_list( attr_list );
1371                 if (rc != LDAP_SUCCESS) {
1372                         return NT_STATUS_UNSUCCESSFUL;
1373                 }
1374                 pdb_set_backend_private_data(newpwd, result, private_data_free_fn, my_methods, PDB_CHANGED);
1375         }
1376
1377         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
1378                 DEBUG(0, ("ldapsam_update_sam_account: No user to modify!\n"));
1379                 return NT_STATUS_UNSUCCESSFUL;
1380         }
1381
1382         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1383         dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
1384         if (!dn) {
1385                 return NT_STATUS_UNSUCCESSFUL;
1386         }
1387
1388         DEBUG(4, ("ldapsam_update_sam_account: user %s to be modified has dn: %s\n", pdb_get_username(newpwd), dn));
1389
1390         if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1391                                 element_is_changed)) {
1392                 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1393                 SAFE_FREE(dn);
1394                 if (mods != NULL)
1395                         ldap_mods_free(mods,True);
1396                 return NT_STATUS_UNSUCCESSFUL;
1397         }
1398         
1399         if (mods == NULL) {
1400                 DEBUG(4,("ldapsam_update_sam_account: mods is empty: nothing to update for user: %s\n",
1401                          pdb_get_username(newpwd)));
1402                 SAFE_FREE(dn);
1403                 return NT_STATUS_OK;
1404         }
1405         
1406         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
1407         ldap_mods_free(mods,True);
1408         SAFE_FREE(dn);
1409
1410         if (!NT_STATUS_IS_OK(ret)) {
1411                 char *ld_error = NULL;
1412                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1413                                 &ld_error);
1414                 DEBUG(0,("ldapsam_update_sam_account: failed to modify user with uid = %s, error: %s (%s)\n",
1415                          pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
1416                 SAFE_FREE(ld_error);
1417                 return ret;
1418         }
1419
1420         DEBUG(2, ("ldapsam_update_sam_account: successfully modified uid = %s in the LDAP database\n",
1421                   pdb_get_username(newpwd)));
1422         return NT_STATUS_OK;
1423 }
1424
1425 /**********************************************************************
1426  Helper function to determine for update_sam_account whether
1427  we need LDAP modification.
1428  *********************************************************************/
1429
1430 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
1431                                       enum pdb_elements element)
1432 {
1433         return (IS_SAM_SET(sampass, element) ||
1434                 IS_SAM_CHANGED(sampass, element));
1435 }
1436
1437 /**********************************************************************
1438  Add SAM_ACCOUNT to LDAP.
1439 *********************************************************************/
1440
1441 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1442 {
1443         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1444         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1445         int rc;
1446         LDAPMessage     *result = NULL;
1447         LDAPMessage     *entry  = NULL;
1448         pstring         dn;
1449         LDAPMod         **mods = NULL;
1450         int             ldap_op = LDAP_MOD_REPLACE;
1451         uint32          num_result;
1452         char            **attr_list;
1453         char            *escape_user;
1454         const char      *username = pdb_get_username(newpwd);
1455         const DOM_SID   *sid = pdb_get_user_sid(newpwd);
1456         pstring         filter;
1457         fstring         sid_string;
1458
1459         if (!username || !*username) {
1460                 DEBUG(0, ("ldapsam_add_sam_account: Cannot add user without a username!\n"));
1461                 return NT_STATUS_INVALID_PARAMETER;
1462         }
1463
1464         /* free this list after the second search or in case we exit on failure */
1465         attr_list = get_userattr_list(ldap_state->schema_ver);
1466
1467         rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
1468
1469         if (rc != LDAP_SUCCESS) {
1470                 free_attr_list( attr_list );
1471                 return NT_STATUS_UNSUCCESSFUL;
1472         }
1473
1474         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
1475                 DEBUG(0,("ldapsam_add_sam_account: User '%s' already in the base, with samba attributes\n", 
1476                          username));
1477                 ldap_msgfree(result);
1478                 free_attr_list( attr_list );
1479                 return NT_STATUS_UNSUCCESSFUL;
1480         }
1481         ldap_msgfree(result);
1482         result = NULL;
1483
1484         if (element_is_set_or_changed(newpwd, PDB_USERSID)) {
1485                 rc = ldapsam_get_ldap_user_by_sid(ldap_state, 
1486                                                   sid, &result); 
1487                 if (rc == LDAP_SUCCESS) {
1488                         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
1489                                 DEBUG(0,("ldapsam_add_sam_account: SID '%s' already in the base, with samba attributes\n", 
1490                                          sid_to_string(sid_string, sid)));
1491                                 free_attr_list( attr_list );
1492                                 ldap_msgfree(result);
1493                                 return NT_STATUS_UNSUCCESSFUL;
1494                         }
1495                         ldap_msgfree(result);
1496                 }
1497         }
1498
1499         /* does the entry already exist but without a samba attributes?
1500            we need to return the samba attributes here */
1501            
1502         escape_user = escape_ldap_string_alloc( username );
1503         pstrcpy( filter, lp_ldap_filter() );
1504         all_string_sub( filter, "%u", escape_user, sizeof(filter) );
1505         SAFE_FREE( escape_user );
1506
1507         rc = smbldap_search_suffix(ldap_state->smbldap_state, 
1508                                    filter, attr_list, &result);
1509         if ( rc != LDAP_SUCCESS ) {
1510                 free_attr_list( attr_list );
1511                 return NT_STATUS_UNSUCCESSFUL;
1512         }
1513
1514         num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1515         
1516         if (num_result > 1) {
1517                 DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
1518                 free_attr_list( attr_list );
1519                 ldap_msgfree(result);
1520                 return NT_STATUS_UNSUCCESSFUL;
1521         }
1522         
1523         /* Check if we need to update an existing entry */
1524         if (num_result == 1) {
1525                 char *tmp;
1526                 
1527                 DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
1528                 ldap_op = LDAP_MOD_REPLACE;
1529                 entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
1530                 tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
1531                 if (!tmp) {
1532                         free_attr_list( attr_list );
1533                         ldap_msgfree(result);
1534                         return NT_STATUS_UNSUCCESSFUL;
1535                 }
1536                 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1537                 SAFE_FREE(tmp);
1538
1539         } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) {
1540
1541                 /* There might be a SID for this account already - say an idmap entry */
1542
1543                 pstr_sprintf(filter, "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))", 
1544                          get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
1545                          sid_to_string(sid_string, sid),
1546                          LDAP_OBJ_IDMAP_ENTRY,
1547                          LDAP_OBJ_SID_ENTRY);
1548                 
1549                 /* free old result before doing a new search */
1550                 if (result != NULL) {
1551                         ldap_msgfree(result);
1552                         result = NULL;
1553                 }
1554                 rc = smbldap_search_suffix(ldap_state->smbldap_state, 
1555                                            filter, attr_list, &result);
1556                         
1557                 if ( rc != LDAP_SUCCESS ) {
1558                         free_attr_list( attr_list );
1559                         return NT_STATUS_UNSUCCESSFUL;
1560                 }
1561                 
1562                 num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1563                 
1564                 if (num_result > 1) {
1565                         DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
1566                         free_attr_list( attr_list );
1567                         ldap_msgfree(result);
1568                         return NT_STATUS_UNSUCCESSFUL;
1569                 }
1570                 
1571                 /* Check if we need to update an existing entry */
1572                 if (num_result == 1) {
1573                         char *tmp;
1574                         
1575                         DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
1576                         ldap_op = LDAP_MOD_REPLACE;
1577                         entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
1578                         tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
1579                         if (!tmp) {
1580                                 free_attr_list( attr_list );
1581                                 ldap_msgfree(result);
1582                                 return NT_STATUS_UNSUCCESSFUL;
1583                         }
1584                         slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1585                         SAFE_FREE(tmp);
1586                 }
1587         }
1588         
1589         free_attr_list( attr_list );
1590
1591         if (num_result == 0) {
1592                 /* Check if we need to add an entry */
1593                 DEBUG(3,("ldapsam_add_sam_account: Adding new user\n"));
1594                 ldap_op = LDAP_MOD_ADD;
1595                 if (username[strlen(username)-1] == '$') {
1596                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
1597                 } else {
1598                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
1599                 }
1600         }
1601
1602         if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1603                                 element_is_set_or_changed)) {
1604                 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1605                 ldap_msgfree(result);
1606                 if (mods != NULL)
1607                         ldap_mods_free(mods,True);
1608                 return NT_STATUS_UNSUCCESSFUL;          
1609         }
1610         
1611         ldap_msgfree(result);
1612
1613         if (mods == NULL) {
1614                 DEBUG(0,("ldapsam_add_sam_account: mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
1615                 return NT_STATUS_UNSUCCESSFUL;
1616         }
1617         switch ( ldap_state->schema_ver ) {
1618                 case SCHEMAVER_SAMBAACCOUNT:
1619                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT);
1620                         break;
1621                 case SCHEMAVER_SAMBASAMACCOUNT:
1622                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT);
1623                         break;
1624                 default:
1625                         DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
1626                         break;
1627         }
1628
1629         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
1630         if (!NT_STATUS_IS_OK(ret)) {
1631                 DEBUG(0,("ldapsam_add_sam_account: failed to modify/add user with uid = %s (dn = %s)\n",
1632                          pdb_get_username(newpwd),dn));
1633                 ldap_mods_free(mods, True);
1634                 return ret;
1635         }
1636
1637         DEBUG(2,("ldapsam_add_sam_account: added: uid == %s in the LDAP database\n", pdb_get_username(newpwd)));
1638         ldap_mods_free(mods, True);
1639         
1640         return NT_STATUS_OK;
1641 }
1642
1643 /**********************************************************************
1644  *********************************************************************/
1645
1646 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
1647                                      const char *filter,
1648                                      LDAPMessage ** result)
1649 {
1650         int scope = LDAP_SCOPE_SUBTREE;
1651         int rc;
1652         char **attr_list;
1653
1654         attr_list = get_attr_list(groupmap_attr_list);
1655         rc = smbldap_search(ldap_state->smbldap_state, 
1656                             lp_ldap_group_suffix (), scope,
1657                             filter, attr_list, 0, result);
1658         free_attr_list( attr_list );
1659
1660         if (rc != LDAP_SUCCESS) {
1661                 char *ld_error = NULL;
1662                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1663                                 &ld_error);
1664                 DEBUG(0, ("ldapsam_search_one_group: "
1665                           "Problem during the LDAP search: LDAP error: %s (%s)\n",
1666                           ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
1667                 DEBUGADD(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
1668                           lp_ldap_group_suffix(), filter));
1669                 SAFE_FREE(ld_error);
1670         }
1671
1672         return rc;
1673 }
1674
1675 /**********************************************************************
1676  *********************************************************************/
1677
1678 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
1679                                  GROUP_MAP *map, LDAPMessage *entry)
1680 {
1681         pstring temp;
1682
1683         if (ldap_state == NULL || map == NULL || entry == NULL ||
1684                         ldap_state->smbldap_state->ldap_struct == NULL) {
1685                 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
1686                 return False;
1687         }
1688
1689         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
1690                         get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp)) {
1691                 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n", 
1692                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GIDNUMBER)));
1693                 return False;
1694         }
1695         DEBUG(2, ("init_group_from_ldap: Entry found for group: %s\n", temp));
1696
1697         map->gid = (gid_t)atol(temp);
1698
1699         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
1700                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp)) {
1701                 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n",
1702                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID)));
1703                 return False;
1704         }
1705         
1706         if (!string_to_sid(&map->sid, temp)) {
1707                 DEBUG(1, ("SID string [%s] could not be read as a valid SID\n", temp));
1708                 return False;
1709         }
1710
1711         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
1712                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp)) {
1713                 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n",
1714                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
1715                 return False;
1716         }
1717         map->sid_name_use = (enum SID_NAME_USE)atol(temp);
1718
1719         if ((map->sid_name_use < SID_NAME_USER) ||
1720                         (map->sid_name_use > SID_NAME_UNKNOWN)) {
1721                 DEBUG(0, ("init_group_from_ldap: Unknown Group type: %d\n", map->sid_name_use));
1722                 return False;
1723         }
1724
1725         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
1726                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp)) {
1727                 temp[0] = '\0';
1728                 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
1729                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp)) 
1730                 {
1731                         DEBUG(0, ("init_group_from_ldap: Attributes cn not found either \
1732 for gidNumber(%lu)\n",(unsigned long)map->gid));
1733                         return False;
1734                 }
1735         }
1736         fstrcpy(map->nt_name, temp);
1737
1738         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
1739                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp)) {
1740                 temp[0] = '\0';
1741         }
1742         fstrcpy(map->comment, temp);
1743
1744         return True;
1745 }
1746
1747 /**********************************************************************
1748  *********************************************************************/
1749
1750 static BOOL init_ldap_from_group(LDAP *ldap_struct,
1751                                  LDAPMessage *existing,
1752                                  LDAPMod ***mods,
1753                                  const GROUP_MAP *map)
1754 {
1755         pstring tmp;
1756
1757         if (mods == NULL || map == NULL) {
1758                 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
1759                 return False;
1760         }
1761
1762         *mods = NULL;
1763
1764         sid_to_string(tmp, &map->sid);
1765
1766         smbldap_make_mod(ldap_struct, existing, mods, 
1767                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp);
1768         pstr_sprintf(tmp, "%i", map->sid_name_use);
1769         smbldap_make_mod(ldap_struct, existing, mods, 
1770                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp);
1771
1772         smbldap_make_mod(ldap_struct, existing, mods, 
1773                 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name);
1774         smbldap_make_mod(ldap_struct, existing, mods, 
1775                 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment);
1776
1777         return True;
1778 }
1779
1780 /**********************************************************************
1781  *********************************************************************/
1782
1783 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
1784                                  const char *filter,
1785                                  GROUP_MAP *map)
1786 {
1787         struct ldapsam_privates *ldap_state =
1788                 (struct ldapsam_privates *)methods->private_data;
1789         LDAPMessage *result = NULL;
1790         LDAPMessage *entry = NULL;
1791         int count;
1792
1793         if (ldapsam_search_one_group(ldap_state, filter, &result)
1794             != LDAP_SUCCESS) {
1795                 return NT_STATUS_NO_SUCH_GROUP;
1796         }
1797
1798         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1799
1800         if (count < 1) {
1801                 DEBUG(4, ("ldapsam_getgroup: Did not find group\n"));
1802                 ldap_msgfree(result);
1803                 return NT_STATUS_NO_SUCH_GROUP;
1804         }
1805
1806         if (count > 1) {
1807                 DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: count=%d\n",
1808                           filter, count));
1809                 ldap_msgfree(result);
1810                 return NT_STATUS_NO_SUCH_GROUP;
1811         }
1812
1813         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1814
1815         if (!entry) {
1816                 ldap_msgfree(result);
1817                 return NT_STATUS_UNSUCCESSFUL;
1818         }
1819
1820         if (!init_group_from_ldap(ldap_state, map, entry)) {
1821                 DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for group filter %s\n",
1822                           filter));
1823                 ldap_msgfree(result);
1824                 return NT_STATUS_NO_SUCH_GROUP;
1825         }
1826
1827         ldap_msgfree(result);
1828         return NT_STATUS_OK;
1829 }
1830
1831 /**********************************************************************
1832  *********************************************************************/
1833
1834 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1835                                  DOM_SID sid)
1836 {
1837         pstring filter;
1838
1839         pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
1840                 LDAP_OBJ_GROUPMAP, 
1841                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID),
1842                 sid_string_static(&sid));
1843
1844         return ldapsam_getgroup(methods, filter, map);
1845 }
1846
1847 /**********************************************************************
1848  *********************************************************************/
1849
1850 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1851                                  gid_t gid)
1852 {
1853         pstring filter;
1854
1855         pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
1856                 LDAP_OBJ_GROUPMAP,
1857                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
1858                 (unsigned long)gid);
1859
1860         return ldapsam_getgroup(methods, filter, map);
1861 }
1862
1863 /**********************************************************************
1864  *********************************************************************/
1865
1866 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1867                                  const char *name)
1868 {
1869         pstring filter;
1870         char *escape_name = escape_ldap_string_alloc(name);
1871
1872         if (!escape_name) {
1873                 return NT_STATUS_NO_MEMORY;
1874         }
1875
1876         pstr_sprintf(filter, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
1877                 LDAP_OBJ_GROUPMAP,
1878                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name,
1879                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), escape_name);
1880
1881         SAFE_FREE(escape_name);
1882
1883         return ldapsam_getgroup(methods, filter, map);
1884 }
1885
1886 /**********************************************************************
1887  *********************************************************************/
1888
1889 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
1890                                            gid_t gid,
1891                                            LDAPMessage **result)
1892 {
1893         pstring filter;
1894
1895         pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))", 
1896                 LDAP_OBJ_POSIXGROUP,
1897                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
1898                 (unsigned long)gid);
1899
1900         return ldapsam_search_one_group(ldap_state, filter, result);
1901 }
1902
1903 /**********************************************************************
1904  *********************************************************************/
1905
1906 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
1907                                                 GROUP_MAP *map)
1908 {
1909         struct ldapsam_privates *ldap_state =
1910                 (struct ldapsam_privates *)methods->private_data;
1911         LDAPMessage *result = NULL;
1912         LDAPMod **mods = NULL;
1913         int count;
1914
1915         char *tmp;
1916         pstring dn;
1917         LDAPMessage *entry;
1918
1919         GROUP_MAP dummy;
1920
1921         int rc;
1922
1923         if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
1924                                              map->gid))) {
1925                 DEBUG(0, ("ldapsam_add_group_mapping_entry: Group %ld already exists in LDAP\n", (unsigned long)map->gid));
1926                 return NT_STATUS_UNSUCCESSFUL;
1927         }
1928
1929         rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
1930         if (rc != LDAP_SUCCESS) {
1931                 ldap_msgfree(result);
1932                 return NT_STATUS_UNSUCCESSFUL;
1933         }
1934
1935         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1936
1937         if ( count == 0 ) {
1938                 ldap_msgfree(result);
1939                 return NT_STATUS_UNSUCCESSFUL;
1940         }
1941
1942         if (count > 1) {
1943                 DEBUG(2, ("ldapsam_add_group_mapping_entry: Group %lu must exist exactly once in LDAP\n",
1944                           (unsigned long)map->gid));
1945                 ldap_msgfree(result);
1946                 return NT_STATUS_UNSUCCESSFUL;
1947         }
1948
1949         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1950         tmp = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
1951         if (!tmp) {
1952                 ldap_msgfree(result);
1953                 return NT_STATUS_UNSUCCESSFUL;
1954         }
1955         pstrcpy(dn, tmp);
1956         SAFE_FREE(tmp);
1957
1958         if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
1959                                   result, &mods, map)) {
1960                 DEBUG(0, ("ldapsam_add_group_mapping_entry: init_ldap_from_group failed!\n"));
1961                 ldap_mods_free(mods, True);
1962                 ldap_msgfree(result);
1963                 return NT_STATUS_UNSUCCESSFUL;
1964         }
1965
1966         ldap_msgfree(result);
1967
1968         if (mods == NULL) {
1969                 DEBUG(0, ("ldapsam_add_group_mapping_entry: mods is empty\n"));
1970                 return NT_STATUS_UNSUCCESSFUL;
1971         }
1972
1973         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP );
1974
1975         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1976         ldap_mods_free(mods, True);
1977
1978         if (rc != LDAP_SUCCESS) {
1979                 char *ld_error = NULL;
1980                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1981                                 &ld_error);
1982                 DEBUG(0, ("ldapsam_add_group_mapping_entry: failed to add group %lu error: %s (%s)\n", (unsigned long)map->gid, 
1983                           ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
1984                 SAFE_FREE(ld_error);
1985                 return NT_STATUS_UNSUCCESSFUL;
1986         }
1987
1988         DEBUG(2, ("ldapsam_add_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
1989         return NT_STATUS_OK;
1990 }
1991
1992 /**********************************************************************
1993  *********************************************************************/
1994
1995 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
1996                                                    GROUP_MAP *map)
1997 {
1998         struct ldapsam_privates *ldap_state =
1999                 (struct ldapsam_privates *)methods->private_data;
2000         int rc;
2001         char *dn = NULL;
2002         LDAPMessage *result = NULL;
2003         LDAPMessage *entry = NULL;
2004         LDAPMod **mods = NULL;
2005
2006         rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2007
2008         if (rc != LDAP_SUCCESS) {
2009                 return NT_STATUS_UNSUCCESSFUL;
2010         }
2011
2012         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
2013                 DEBUG(0, ("ldapsam_update_group_mapping_entry: No group to modify!\n"));
2014                 ldap_msgfree(result);
2015                 return NT_STATUS_UNSUCCESSFUL;
2016         }
2017
2018         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
2019
2020         if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
2021                                   result, &mods, map)) {
2022                 DEBUG(0, ("ldapsam_update_group_mapping_entry: init_ldap_from_group failed\n"));
2023                 ldap_msgfree(result);
2024                 if (mods != NULL)
2025                         ldap_mods_free(mods,True);
2026                 return NT_STATUS_UNSUCCESSFUL;
2027         }
2028
2029         if (mods == NULL) {
2030                 DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: nothing to do\n"));
2031                 ldap_msgfree(result);
2032                 return NT_STATUS_OK;
2033         }
2034
2035         dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
2036         if (!dn) {
2037                 ldap_msgfree(result);
2038                 return NT_STATUS_UNSUCCESSFUL;
2039         }
2040         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
2041         SAFE_FREE(dn);
2042
2043         ldap_mods_free(mods, True);
2044         ldap_msgfree(result);
2045
2046         if (rc != LDAP_SUCCESS) {
2047                 char *ld_error = NULL;
2048                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2049                                 &ld_error);
2050                 DEBUG(0, ("ldapsam_update_group_mapping_entry: failed to modify group %lu error: %s (%s)\n", (unsigned long)map->gid, 
2051                           ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2052                 SAFE_FREE(ld_error);
2053                 return NT_STATUS_UNSUCCESSFUL;
2054         }
2055
2056         DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
2057         return NT_STATUS_OK;
2058 }
2059
2060 /**********************************************************************
2061  *********************************************************************/
2062
2063 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2064                                                    DOM_SID sid)
2065 {
2066         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)methods->private_data;
2067         pstring sidstring, filter;
2068         LDAPMessage *result = NULL;
2069         int rc;
2070         NTSTATUS ret;
2071         char **attr_list;
2072
2073         sid_to_string(sidstring, &sid);
2074         
2075         pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", 
2076                 LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID, sidstring);
2077
2078         rc = ldapsam_search_one_group(ldap_state, filter, &result);
2079
2080         if (rc != LDAP_SUCCESS) {
2081                 return NT_STATUS_NO_SUCH_GROUP;
2082         }
2083
2084         attr_list = get_attr_list( groupmap_attr_list_to_delete );
2085         ret = ldapsam_delete_entry(ldap_state, result, LDAP_OBJ_GROUPMAP, attr_list);
2086         free_attr_list ( attr_list );
2087
2088         ldap_msgfree(result);
2089
2090         return ret;
2091 }
2092
2093 /**********************************************************************
2094  *********************************************************************/
2095
2096 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
2097 {
2098         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2099         fstring filter;
2100         int rc;
2101         char **attr_list;
2102
2103         pstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
2104         attr_list = get_attr_list( groupmap_attr_list );
2105         rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
2106                             LDAP_SCOPE_SUBTREE, filter,
2107                             attr_list, 0, &ldap_state->result);
2108         free_attr_list( attr_list );
2109
2110         if (rc != LDAP_SUCCESS) {
2111                 DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n", ldap_err2string(rc)));
2112                 DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n", lp_ldap_group_suffix(), filter));
2113                 ldap_msgfree(ldap_state->result);
2114                 ldap_state->result = NULL;
2115                 return NT_STATUS_UNSUCCESSFUL;
2116         }
2117
2118         DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2119                   ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
2120                                      ldap_state->result)));
2121
2122         ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result);
2123         ldap_state->index = 0;
2124
2125         return NT_STATUS_OK;
2126 }
2127
2128 /**********************************************************************
2129  *********************************************************************/
2130
2131 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2132 {
2133         ldapsam_endsampwent(my_methods);
2134 }
2135
2136 /**********************************************************************
2137  *********************************************************************/
2138
2139 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
2140                                     GROUP_MAP *map)
2141 {
2142         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2143         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2144         BOOL bret = False;
2145
2146         while (!bret) {
2147                 if (!ldap_state->entry)
2148                         return ret;
2149                 
2150                 ldap_state->index++;
2151                 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
2152                 
2153                 ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
2154                                             ldap_state->entry); 
2155         }
2156
2157         return NT_STATUS_OK;
2158 }
2159
2160 /**********************************************************************
2161  *********************************************************************/
2162
2163 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
2164                                            enum SID_NAME_USE sid_name_use,
2165                                            GROUP_MAP **rmap, int *num_entries,
2166                                            BOOL unix_only)
2167 {
2168         GROUP_MAP map;
2169         GROUP_MAP *mapt;
2170         int entries = 0;
2171
2172         *num_entries = 0;
2173         *rmap = NULL;
2174
2175         if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
2176                 DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open passdb\n"));
2177                 return NT_STATUS_ACCESS_DENIED;
2178         }
2179
2180         while (NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, &map))) {
2181                 if (sid_name_use != SID_NAME_UNKNOWN &&
2182                     sid_name_use != map.sid_name_use) {
2183                         DEBUG(11,("ldapsam_enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
2184                         continue;
2185                 }
2186                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
2187                         DEBUG(11,("ldapsam_enum_group_mapping: group %s is non mapped\n", map.nt_name));
2188                         continue;
2189                 }
2190
2191                 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
2192                 if (!mapt) {
2193                         DEBUG(0,("ldapsam_enum_group_mapping: Unable to enlarge group map!\n"));
2194                         SAFE_FREE(*rmap);
2195                         return NT_STATUS_UNSUCCESSFUL;
2196                 }
2197                 else
2198                         (*rmap) = mapt;
2199
2200                 mapt[entries] = map;
2201
2202                 entries += 1;
2203
2204         }
2205         ldapsam_endsamgrent(methods);
2206
2207         *num_entries = entries;
2208
2209         return NT_STATUS_OK;
2210 }
2211
2212 /**********************************************************************
2213  Housekeeping
2214  *********************************************************************/
2215
2216 static void free_private_data(void **vp) 
2217 {
2218         struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2219
2220         smbldap_free_struct(&(*ldap_state)->smbldap_state);
2221
2222         if ((*ldap_state)->result != NULL) {
2223                 ldap_msgfree((*ldap_state)->result);
2224                 (*ldap_state)->result = NULL;
2225         }
2226
2227         *ldap_state = NULL;
2228
2229         /* No need to free any further, as it is talloc()ed */
2230 }
2231
2232 /**********************************************************************
2233  Intitalise the parts of the pdb_context that are common to all pdb_ldap modes
2234  *********************************************************************/
2235
2236 static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, 
2237                                         const char *location)
2238 {
2239         NTSTATUS nt_status;
2240         struct ldapsam_privates *ldap_state;
2241
2242         if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
2243                 return nt_status;
2244         }
2245
2246         (*pdb_method)->name = "ldapsam";
2247
2248         (*pdb_method)->setsampwent = ldapsam_setsampwent;
2249         (*pdb_method)->endsampwent = ldapsam_endsampwent;
2250         (*pdb_method)->getsampwent = ldapsam_getsampwent;
2251         (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
2252         (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
2253         (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
2254         (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
2255         (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
2256
2257         (*pdb_method)->getgrsid = ldapsam_getgrsid;
2258         (*pdb_method)->getgrgid = ldapsam_getgrgid;
2259         (*pdb_method)->getgrnam = ldapsam_getgrnam;
2260         (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
2261         (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
2262         (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
2263         (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
2264
2265         /* TODO: Setup private data and free */
2266
2267         ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(*ldap_state));
2268         if (!ldap_state) {
2269                 DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n"));
2270                 return NT_STATUS_NO_MEMORY;
2271         }
2272
2273         if (!NT_STATUS_IS_OK(nt_status = 
2274                              smbldap_init(pdb_context->mem_ctx, location, 
2275                                           &ldap_state->smbldap_state)));
2276
2277         ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
2278         if (!ldap_state->domain_name) {
2279                 return NT_STATUS_NO_MEMORY;
2280         }
2281
2282         (*pdb_method)->private_data = ldap_state;
2283
2284         (*pdb_method)->free_private_data = free_private_data;
2285
2286         return NT_STATUS_OK;
2287 }
2288
2289 /**********************************************************************
2290  Initialise the 'compat' mode for pdb_ldap
2291  *********************************************************************/
2292
2293 static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2294 {
2295         NTSTATUS nt_status;
2296         struct ldapsam_privates *ldap_state;
2297
2298 #ifdef WITH_LDAP_SAMCONFIG
2299         if (!location) {
2300                 int ldap_port = lp_ldap_port();
2301                         
2302                 /* remap default port if not using SSL (ie clear or TLS) */
2303                 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
2304                         ldap_port = 389;
2305                 }
2306
2307                 location = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
2308                 if (!location) {
2309                         return NT_STATUS_NO_MEMORY;
2310                 }
2311         }
2312 #endif
2313
2314         if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
2315                 return nt_status;
2316         }
2317
2318         (*pdb_method)->name = "ldapsam_compat";
2319
2320         ldap_state = (*pdb_method)->private_data;
2321         ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
2322
2323         sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
2324
2325         return NT_STATUS_OK;
2326 }
2327
2328 /**********************************************************************
2329  Initialise the normal mode for pdb_ldap
2330  *********************************************************************/
2331
2332 static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2333 {
2334         NTSTATUS nt_status;
2335         struct ldapsam_privates *ldap_state;
2336         uint32 alg_rid_base;
2337         pstring alg_rid_base_string;
2338         LDAPMessage *result = NULL;
2339         LDAPMessage *entry = NULL;
2340         DOM_SID ldap_domain_sid;
2341         DOM_SID secrets_domain_sid;
2342         pstring domain_sid_string;
2343
2344         if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
2345                 return nt_status;
2346         }
2347
2348         (*pdb_method)->name = "ldapsam";
2349
2350         ldap_state = (*pdb_method)->private_data;
2351         ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
2352
2353         /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
2354         
2355         nt_status = smbldap_search_domain_info(ldap_state->smbldap_state, &result, 
2356                 ldap_state->domain_name, True);
2357         
2358         if ( !NT_STATUS_IS_OK(nt_status) ) {
2359                 DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain info, nor add one to the domain\n"));
2360                 DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, will be unable to allocate new users/groups, \
2361 and will risk BDCs having inconsistant SIDs\n"));
2362                 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
2363                 return NT_STATUS_OK;
2364         }
2365
2366         /* Given that the above might fail, everything below this must be optional */
2367         
2368         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
2369         if (!entry) {
2370                 DEBUG(0, ("pdb_init_ldapsam: Could not get domain info entry\n"));
2371                 ldap_msgfree(result);
2372                 return NT_STATUS_UNSUCCESSFUL;
2373         }
2374
2375         if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
2376                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), 
2377                                  domain_sid_string)) {
2378                 BOOL found_sid;
2379                 if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
2380                         DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be read as a valid SID\n", domain_sid_string));
2381                         return NT_STATUS_INVALID_PARAMETER;
2382                 }
2383                 found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid);
2384                 if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) {
2385                         /* reset secrets.tdb sid */
2386                         secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid);
2387                 }
2388                 sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
2389         }
2390
2391         if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
2392                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ALGORITHMIC_RID_BASE), 
2393                                  alg_rid_base_string)) {
2394                 alg_rid_base = (uint32)atol(alg_rid_base_string);
2395                 if (alg_rid_base != algorithmic_rid_base()) {
2396                         DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n"
2397                                   "database was initialised.  Aborting. \n"));
2398                         ldap_msgfree(result);
2399                         return NT_STATUS_UNSUCCESSFUL;
2400                 }
2401         }
2402         ldap_msgfree(result);
2403
2404         return NT_STATUS_OK;
2405 }
2406
2407 NTSTATUS pdb_ldap_init(void)
2408 {
2409         NTSTATUS nt_status;
2410         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
2411                 return nt_status;
2412
2413         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
2414                 return nt_status;
2415
2416         return NT_STATUS_OK;
2417 }