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