trying to get HEAD building again. If you want the code
[tprouty/samba.git] / source / 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_memfree(*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 plaittext 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                 return NT_STATUS_UNSUCCESSFUL;
1381         }
1382         
1383         if (mods == NULL) {
1384                 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
1385                          pdb_get_username(newpwd)));
1386                 ldap_mods_free(mods, True);
1387                 return NT_STATUS_OK;
1388         }
1389         
1390         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
1391         ldap_mods_free(mods,True);
1392
1393         if (!NT_STATUS_IS_OK(ret)) {
1394                 char *ld_error = NULL;
1395                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1396                                 &ld_error);
1397                 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
1398                          pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
1399                 SAFE_FREE(ld_error);
1400                 return ret;
1401         }
1402
1403         DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
1404                   pdb_get_username(newpwd)));
1405         return NT_STATUS_OK;
1406 }
1407
1408 /**********************************************************************
1409   Helper function to determine for update_sam_account whether
1410   we need LDAP modification.
1411  *********************************************************************/
1412 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
1413                                       enum pdb_elements element)
1414 {
1415         return (IS_SAM_SET(sampass, element) ||
1416                 IS_SAM_CHANGED(sampass, element));
1417 }
1418
1419 /**********************************************************************
1420 Add SAM_ACCOUNT to LDAP 
1421 *********************************************************************/
1422
1423 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1424 {
1425         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1426         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1427         int rc;
1428         LDAPMessage     *result = NULL;
1429         LDAPMessage     *entry  = NULL;
1430         pstring         dn;
1431         LDAPMod         **mods = NULL;
1432         int             ldap_op;
1433         uint32          num_result;
1434         char            **attr_list;
1435         char            *escape_user;
1436         const char      *username = pdb_get_username(newpwd);
1437         const DOM_SID   *sid = pdb_get_user_sid(newpwd);
1438         pstring         filter;
1439         fstring         sid_string;
1440
1441         if (!username || !*username) {
1442                 DEBUG(0, ("Cannot add user without a username!\n"));
1443                 return NT_STATUS_INVALID_PARAMETER;
1444         }
1445
1446         /* free this list after the second search or in case we exit on failure */
1447         attr_list = get_userattr_list(ldap_state->schema_ver);
1448
1449         rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
1450
1451         if (rc != LDAP_SUCCESS) {
1452                 free_attr_list( attr_list );
1453                 return NT_STATUS_UNSUCCESSFUL;
1454         }
1455
1456         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
1457                 DEBUG(0,("User '%s' already in the base, with samba attributes\n", 
1458                          username));
1459                 ldap_msgfree(result);
1460                 free_attr_list( attr_list );
1461                 return NT_STATUS_UNSUCCESSFUL;
1462         }
1463         ldap_msgfree(result);
1464         result = NULL;
1465
1466         if (element_is_set_or_changed(newpwd, PDB_USERSID)) {
1467                 rc = ldapsam_get_ldap_user_by_sid(ldap_state, 
1468                                                   sid, &result); 
1469                 if (rc == LDAP_SUCCESS) {
1470                         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
1471                                 DEBUG(0,("SID '%s' already in the base, with samba attributes\n", 
1472                                          sid_to_string(sid_string, sid)));
1473                                 free_attr_list( attr_list );
1474                                 return NT_STATUS_UNSUCCESSFUL;
1475                         }
1476                         ldap_msgfree(result);
1477                 }
1478         }
1479
1480         /* does the entry already exist but without a samba attributes?
1481            we need to return the samba attributes here */
1482            
1483         escape_user = escape_ldap_string_alloc( username );
1484         pstrcpy( filter, lp_ldap_filter() );
1485         all_string_sub( filter, "%u", escape_user, sizeof(filter) );
1486         SAFE_FREE( escape_user );
1487
1488         rc = smbldap_search_suffix(ldap_state->smbldap_state, 
1489                                    filter, attr_list, &result);
1490         if ( rc != LDAP_SUCCESS ) {
1491                 free_attr_list( attr_list );
1492                 return NT_STATUS_UNSUCCESSFUL;
1493         }
1494
1495         num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1496         
1497         if (num_result > 1) {
1498                 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1499                 free_attr_list( attr_list );
1500                 ldap_msgfree(result);
1501                 return NT_STATUS_UNSUCCESSFUL;
1502         }
1503         
1504         /* Check if we need to update an existing entry */
1505         if (num_result == 1) {
1506                 char *tmp;
1507                 
1508                 DEBUG(3,("User exists without samba attributes: adding them\n"));
1509                 ldap_op = LDAP_MOD_REPLACE;
1510                 entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
1511                 tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
1512                 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1513                 ldap_memfree (tmp);
1514
1515         } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) {
1516
1517                 /* There might be a SID for this account already - say an idmap entry */
1518
1519                 snprintf(filter, sizeof(filter)-1, "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))", 
1520                          get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
1521                          sid_to_string(sid_string, sid),
1522                          LDAP_OBJ_IDMAP_ENTRY,
1523                          LDAP_OBJ_SID_ENTRY);
1524                 
1525                 rc = smbldap_search_suffix(ldap_state->smbldap_state, 
1526                                            filter, attr_list, &result);
1527                         
1528                 if ( rc != LDAP_SUCCESS ) {
1529                         free_attr_list( attr_list );
1530                         return NT_STATUS_UNSUCCESSFUL;
1531                 }
1532                 
1533                 num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1534                 
1535                 if (num_result > 1) {
1536                         DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1537                         free_attr_list( attr_list );
1538                         ldap_msgfree(result);
1539                         return NT_STATUS_UNSUCCESSFUL;
1540                 }
1541                 
1542                 /* Check if we need to update an existing entry */
1543                 if (num_result == 1) {
1544                         char *tmp;
1545                         
1546                         DEBUG(3,("User exists without samba attributes: adding them\n"));
1547                         ldap_op = LDAP_MOD_REPLACE;
1548                         entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
1549                         tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
1550                         slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1551                         ldap_memfree (tmp);
1552                 }
1553         }
1554         
1555         free_attr_list( attr_list );
1556
1557         if (num_result == 0) {
1558                 /* Check if we need to add an entry */
1559                 DEBUG(3,("Adding new user\n"));
1560                 ldap_op = LDAP_MOD_ADD;
1561                 if (username[strlen(username)-1] == '$') {
1562                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
1563                 } else {
1564                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
1565                 }
1566         }
1567
1568         if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1569                                 element_is_set_or_changed)) {
1570                 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1571                 ldap_msgfree(result);
1572                 return NT_STATUS_UNSUCCESSFUL;          
1573         }
1574         
1575         ldap_msgfree(result);
1576
1577         if (mods == NULL) {
1578                 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
1579                 return NT_STATUS_UNSUCCESSFUL;
1580         }
1581         switch ( ldap_state->schema_ver )
1582         {
1583                 case SCHEMAVER_SAMBAACCOUNT:
1584                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT);
1585                         break;
1586                 case SCHEMAVER_SAMBASAMACCOUNT:
1587                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT);
1588                         break;
1589                 default:
1590                         DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
1591                         break;
1592         }
1593
1594         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
1595         if (!NT_STATUS_IS_OK(ret)) {
1596                 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
1597                          pdb_get_username(newpwd),dn));
1598                 ldap_mods_free(mods, True);
1599                 return ret;
1600         }
1601
1602         DEBUG(2,("added: uid == %s in the LDAP database\n", pdb_get_username(newpwd)));
1603         ldap_mods_free(mods, True);
1604         
1605         return NT_STATUS_OK;
1606 }
1607
1608 /**********************************************************************
1609  *********************************************************************/
1610
1611 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
1612                                      const char *filter,
1613                                      LDAPMessage ** result)
1614 {
1615         int scope = LDAP_SCOPE_SUBTREE;
1616         int rc;
1617         char **attr_list;
1618
1619         DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
1620
1621
1622         attr_list = get_attr_list(groupmap_attr_list);
1623         rc = smbldap_search(ldap_state->smbldap_state, 
1624                             lp_ldap_group_suffix (), scope,
1625                             filter, attr_list, 0, result);
1626         free_attr_list( attr_list );
1627
1628         if (rc != LDAP_SUCCESS) {
1629                 char *ld_error = NULL;
1630                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1631                                 &ld_error);
1632                 DEBUG(0, ("ldapsam_search_one_group: "
1633                           "Problem during the LDAP search: LDAP error: %s (%s)",
1634                           ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
1635                 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
1636                           lp_ldap_group_suffix(), filter));
1637                 SAFE_FREE(ld_error);
1638         }
1639
1640         return rc;
1641 }
1642
1643 /**********************************************************************
1644  *********************************************************************/
1645
1646 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
1647                                  GROUP_MAP *map, LDAPMessage *entry)
1648 {
1649         pstring temp;
1650
1651         if (ldap_state == NULL || map == NULL || entry == NULL ||
1652             ldap_state->smbldap_state->ldap_struct == NULL) 
1653         {
1654                 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
1655                 return False;
1656         }
1657
1658         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
1659                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp)) 
1660         {
1661                 DEBUG(0, ("Mandatory attribute %s not found\n", 
1662                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GIDNUMBER)));
1663                 return False;
1664         }
1665         DEBUG(2, ("Entry found for group: %s\n", temp));
1666
1667         map->gid = (gid_t)atol(temp);
1668
1669         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
1670                 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp)) 
1671         {
1672                 DEBUG(0, ("Mandatory attribute %s not found\n",
1673                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID)));
1674                 return False;
1675         }
1676         string_to_sid(&map->sid, temp);
1677
1678         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
1679                 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp)) 
1680         {
1681                 DEBUG(0, ("Mandatory attribute %s not found\n",
1682                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
1683                 return False;
1684         }
1685         map->sid_name_use = (uint32)atol(temp);
1686
1687         if ((map->sid_name_use < SID_NAME_USER) ||
1688             (map->sid_name_use > SID_NAME_UNKNOWN)) {
1689                 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
1690                 return False;
1691         }
1692
1693         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
1694                 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp)) 
1695         {
1696                 temp[0] = '\0';
1697                 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
1698                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp)) 
1699                 {
1700                         DEBUG(0, ("Attributes cn not found either "
1701                                   "for gidNumber(%i)\n",map->gid));
1702                         return False;
1703                 }
1704         }
1705         fstrcpy(map->nt_name, temp);
1706
1707         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
1708                 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp)) 
1709         {
1710                 temp[0] = '\0';
1711         }
1712         fstrcpy(map->comment, temp);
1713
1714         return True;
1715 }
1716
1717 /**********************************************************************
1718  *********************************************************************/
1719
1720 static BOOL init_ldap_from_group(LDAP *ldap_struct,
1721                                  LDAPMessage *existing,
1722                                  LDAPMod ***mods,
1723                                  const GROUP_MAP *map)
1724 {
1725         pstring tmp;
1726
1727         if (mods == NULL || map == NULL) {
1728                 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
1729                 return False;
1730         }
1731
1732         *mods = NULL;
1733
1734         sid_to_string(tmp, &map->sid);
1735         smbldap_make_mod(ldap_struct, existing, mods, 
1736                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp);
1737         snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
1738         smbldap_make_mod(ldap_struct, existing, mods, 
1739                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp);
1740
1741         smbldap_make_mod(ldap_struct, existing, mods, 
1742                 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name);
1743         smbldap_make_mod(ldap_struct, existing, mods, 
1744                 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment);
1745
1746         return True;
1747 }
1748
1749 /**********************************************************************
1750  *********************************************************************/
1751
1752 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
1753                                  const char *filter,
1754                                  GROUP_MAP *map)
1755 {
1756         struct ldapsam_privates *ldap_state =
1757                 (struct ldapsam_privates *)methods->private_data;
1758         LDAPMessage *result;
1759         LDAPMessage *entry;
1760         int count;
1761
1762         if (ldapsam_search_one_group(ldap_state, filter, &result)
1763             != LDAP_SUCCESS) {
1764                 return NT_STATUS_NO_SUCH_GROUP;
1765         }
1766
1767         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1768
1769         if (count < 1) {
1770                 DEBUG(4, ("Did not find group\n"));
1771                 ldap_msgfree(result);
1772                 return NT_STATUS_NO_SUCH_GROUP;
1773         }
1774
1775         if (count > 1) {
1776                 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
1777                           filter, count));
1778                 ldap_msgfree(result);
1779                 return NT_STATUS_NO_SUCH_GROUP;
1780         }
1781
1782         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1783
1784         if (!entry) {
1785                 ldap_msgfree(result);
1786                 return NT_STATUS_UNSUCCESSFUL;
1787         }
1788
1789         if (!init_group_from_ldap(ldap_state, map, entry)) {
1790                 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
1791                           filter));
1792                 ldap_msgfree(result);
1793                 return NT_STATUS_NO_SUCH_GROUP;
1794         }
1795
1796         ldap_msgfree(result);
1797         return NT_STATUS_OK;
1798 }
1799
1800 /**********************************************************************
1801  *********************************************************************/
1802
1803 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1804                                  DOM_SID sid)
1805 {
1806         pstring filter;
1807
1808         snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
1809                 LDAP_OBJ_GROUPMAP, 
1810                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID),
1811                 sid_string_static(&sid));
1812
1813         return ldapsam_getgroup(methods, filter, map);
1814 }
1815
1816 /**********************************************************************
1817  *********************************************************************/
1818
1819 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1820                                  gid_t gid)
1821 {
1822         pstring filter;
1823
1824         snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%d))",
1825                 LDAP_OBJ_GROUPMAP,
1826                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
1827                 gid);
1828
1829         return ldapsam_getgroup(methods, filter, map);
1830 }
1831
1832 /**********************************************************************
1833  *********************************************************************/
1834
1835 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1836                                  const char *name)
1837 {
1838         pstring filter;
1839         char *escape_name = escape_ldap_string_alloc(name);
1840
1841         if (!escape_name) {
1842                 return NT_STATUS_NO_MEMORY;
1843         }
1844
1845         snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
1846                 LDAP_OBJ_GROUPMAP,
1847                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name,
1848                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), escape_name);
1849
1850         SAFE_FREE(escape_name);
1851
1852         return ldapsam_getgroup(methods, filter, map);
1853 }
1854
1855 /**********************************************************************
1856  *********************************************************************/
1857
1858 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
1859                                            gid_t gid,
1860                                            LDAPMessage **result)
1861 {
1862         pstring filter;
1863
1864         snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%i))", 
1865                 LDAP_OBJ_POSIXGROUP,
1866                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
1867                 gid);
1868
1869         return ldapsam_search_one_group(ldap_state, filter, result);
1870 }
1871
1872 /**********************************************************************
1873  *********************************************************************/
1874
1875 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
1876                                                 GROUP_MAP *map)
1877 {
1878         struct ldapsam_privates *ldap_state =
1879                 (struct ldapsam_privates *)methods->private_data;
1880         LDAPMessage *result = NULL;
1881         LDAPMod **mods = NULL;
1882         int count;
1883
1884         char *tmp;
1885         pstring dn;
1886         LDAPMessage *entry;
1887
1888         GROUP_MAP dummy;
1889
1890         int rc;
1891
1892         if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
1893                                              map->gid))) {
1894                 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
1895                 return NT_STATUS_UNSUCCESSFUL;
1896         }
1897
1898         rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
1899         if (rc != LDAP_SUCCESS) {
1900                 return NT_STATUS_UNSUCCESSFUL;
1901         }
1902
1903         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1904
1905         if ( count == 0 )
1906                 return NT_STATUS_UNSUCCESSFUL;
1907
1908         if (count > 1) {
1909                 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
1910                           map->gid));
1911                 ldap_msgfree(result);
1912                 return NT_STATUS_UNSUCCESSFUL;
1913         }
1914
1915         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1916         tmp = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
1917         pstrcpy(dn, tmp);
1918         ldap_memfree(tmp);
1919
1920         if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
1921                                   result, &mods, map)) {
1922                 DEBUG(0, ("init_ldap_from_group failed!\n"));
1923                 ldap_mods_free(mods, True);
1924                 ldap_msgfree(result);
1925                 return NT_STATUS_UNSUCCESSFUL;
1926         }
1927
1928         ldap_msgfree(result);
1929
1930         if (mods == NULL) {
1931                 DEBUG(0, ("mods is empty\n"));
1932                 return NT_STATUS_UNSUCCESSFUL;
1933         }
1934
1935         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP );
1936
1937         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1938         ldap_mods_free(mods, True);
1939
1940         if (rc != LDAP_SUCCESS) {
1941                 char *ld_error = NULL;
1942                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1943                                 &ld_error);
1944                 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid, 
1945                           ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
1946                 SAFE_FREE(ld_error);
1947                 return NT_STATUS_UNSUCCESSFUL;
1948         }
1949
1950         DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
1951         return NT_STATUS_OK;
1952 }
1953
1954 /**********************************************************************
1955  *********************************************************************/
1956
1957 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
1958                                                    GROUP_MAP *map)
1959 {
1960         struct ldapsam_privates *ldap_state =
1961                 (struct ldapsam_privates *)methods->private_data;
1962         int rc;
1963         char *dn;
1964         LDAPMessage *result;
1965         LDAPMessage *entry;
1966         LDAPMod **mods;
1967
1968         rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
1969
1970         if (rc != LDAP_SUCCESS) {
1971                 return NT_STATUS_UNSUCCESSFUL;
1972         }
1973
1974         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
1975                 DEBUG(0, ("No group to modify!\n"));
1976                 ldap_msgfree(result);
1977                 return NT_STATUS_UNSUCCESSFUL;
1978         }
1979
1980         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1981         dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
1982
1983         if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
1984                                   result, &mods, map)) {
1985                 DEBUG(0, ("init_ldap_from_group failed\n"));
1986                 ldap_msgfree(result);
1987                 return NT_STATUS_UNSUCCESSFUL;
1988         }
1989
1990         ldap_msgfree(result);
1991
1992         if (mods == NULL) {
1993                 DEBUG(4, ("mods is empty: nothing to do\n"));
1994                 return NT_STATUS_UNSUCCESSFUL;
1995         }
1996
1997         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1998
1999         ldap_mods_free(mods, True);
2000
2001         if (rc != LDAP_SUCCESS) {
2002                 char *ld_error = NULL;
2003                 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2004                                 &ld_error);
2005                 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid, 
2006                           ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2007                 SAFE_FREE(ld_error);
2008         }
2009
2010         DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2011         return NT_STATUS_OK;
2012 }
2013
2014 /**********************************************************************
2015  *********************************************************************/
2016
2017 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2018                                                    DOM_SID sid)
2019 {
2020         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)methods->private_data;
2021         pstring sidstring, filter;
2022         LDAPMessage *result;
2023         int rc;
2024         NTSTATUS ret;
2025         char **attr_list;
2026
2027         sid_to_string(sidstring, &sid);
2028         
2029         snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))", 
2030                 LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID, sidstring);
2031
2032         rc = ldapsam_search_one_group(ldap_state, filter, &result);
2033
2034         if (rc != LDAP_SUCCESS) {
2035                 return NT_STATUS_NO_SUCH_GROUP;
2036         }
2037
2038         attr_list = get_attr_list( groupmap_attr_list_to_delete );
2039         ret = ldapsam_delete_entry(ldap_state, result, LDAP_OBJ_GROUPMAP, attr_list);
2040         free_attr_list ( attr_list );
2041
2042         ldap_msgfree(result);
2043
2044         return ret;
2045 }
2046
2047 /**********************************************************************
2048  *********************************************************************/
2049
2050 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
2051 {
2052         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2053         fstring filter;
2054         int rc;
2055         char **attr_list;
2056
2057         snprintf( filter, sizeof(filter)-1, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
2058         attr_list = get_attr_list( groupmap_attr_list );
2059         rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
2060                             LDAP_SCOPE_SUBTREE, filter,
2061                             attr_list, 0, &ldap_state->result);
2062         free_attr_list( attr_list );
2063
2064         if (rc != LDAP_SUCCESS) {
2065                 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2066                 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_group_suffix(), filter));
2067                 ldap_msgfree(ldap_state->result);
2068                 ldap_state->result = NULL;
2069                 return NT_STATUS_UNSUCCESSFUL;
2070         }
2071
2072         DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2073                   ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
2074                                      ldap_state->result)));
2075
2076         ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result);
2077         ldap_state->index = 0;
2078
2079         return NT_STATUS_OK;
2080 }
2081
2082 /**********************************************************************
2083  *********************************************************************/
2084
2085 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2086 {
2087         ldapsam_endsampwent(my_methods);
2088 }
2089
2090 /**********************************************************************
2091  *********************************************************************/
2092
2093 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
2094                                     GROUP_MAP *map)
2095 {
2096         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2097         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2098         BOOL bret = False;
2099
2100         while (!bret) {
2101                 if (!ldap_state->entry)
2102                         return ret;
2103                 
2104                 ldap_state->index++;
2105                 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
2106                 
2107                 ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
2108                                             ldap_state->entry); 
2109         }
2110
2111         return NT_STATUS_OK;
2112 }
2113
2114 /**********************************************************************
2115  *********************************************************************/
2116
2117 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
2118                                            enum SID_NAME_USE sid_name_use,
2119                                            GROUP_MAP **rmap, int *num_entries,
2120                                            BOOL unix_only)
2121 {
2122         GROUP_MAP map;
2123         GROUP_MAP *mapt;
2124         int entries = 0;
2125         NTSTATUS nt_status;
2126
2127         *num_entries = 0;
2128         *rmap = NULL;
2129
2130         if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
2131                 DEBUG(0, ("Unable to open passdb\n"));
2132                 return NT_STATUS_ACCESS_DENIED;
2133         }
2134
2135         while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
2136                 if (sid_name_use != SID_NAME_UNKNOWN &&
2137                     sid_name_use != map.sid_name_use) {
2138                         DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
2139                         continue;
2140                 }
2141                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
2142                         DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
2143                         continue;
2144                 }
2145
2146                 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
2147                 if (!mapt) {
2148                         DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
2149                         SAFE_FREE(*rmap);
2150                         return NT_STATUS_UNSUCCESSFUL;
2151                 }
2152                 else
2153                         (*rmap) = mapt;
2154
2155                 mapt[entries] = map;
2156
2157                 entries += 1;
2158
2159         }
2160         ldapsam_endsamgrent(methods);
2161
2162         *num_entries = entries;
2163
2164         return NT_STATUS_OK;
2165 }
2166
2167 /**********************************************************************
2168  Housekeeping
2169  *********************************************************************/
2170
2171 static void free_private_data(void **vp) 
2172 {
2173         struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2174
2175         smbldap_free_struct(&(*ldap_state)->smbldap_state);
2176
2177         *ldap_state = NULL;
2178
2179         /* No need to free any further, as it is talloc()ed */
2180 }
2181
2182 /**********************************************************************
2183  Intitalise the parts of the pdb_context that are common to all pdb_ldap modes
2184  *********************************************************************/
2185
2186 static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, 
2187                                         const char *location)
2188 {
2189         NTSTATUS nt_status;
2190         struct ldapsam_privates *ldap_state;
2191
2192         if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
2193                 return nt_status;
2194         }
2195
2196         (*pdb_method)->name = "ldapsam";
2197
2198         (*pdb_method)->setsampwent = ldapsam_setsampwent;
2199         (*pdb_method)->endsampwent = ldapsam_endsampwent;
2200         (*pdb_method)->getsampwent = ldapsam_getsampwent;
2201         (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
2202         (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
2203         (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
2204         (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
2205         (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
2206
2207         (*pdb_method)->getgrsid = ldapsam_getgrsid;
2208         (*pdb_method)->getgrgid = ldapsam_getgrgid;
2209         (*pdb_method)->getgrnam = ldapsam_getgrnam;
2210         (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
2211         (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
2212         (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
2213         (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
2214
2215         /* TODO: Setup private data and free */
2216
2217         ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(*ldap_state));
2218         if (!ldap_state) {
2219                 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2220                 return NT_STATUS_NO_MEMORY;
2221         }
2222
2223         if (!NT_STATUS_IS_OK(nt_status = 
2224                              smbldap_init(pdb_context->mem_ctx, location, 
2225                                           &ldap_state->smbldap_state)));
2226
2227         ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
2228         if (!ldap_state->domain_name) {
2229                 return NT_STATUS_NO_MEMORY;
2230         }
2231
2232         (*pdb_method)->private_data = ldap_state;
2233
2234         (*pdb_method)->free_private_data = free_private_data;
2235
2236         return NT_STATUS_OK;
2237 }
2238
2239 /**********************************************************************
2240  Initialise the 'compat' mode for pdb_ldap
2241  *********************************************************************/
2242
2243 static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2244 {
2245         NTSTATUS nt_status;
2246         struct ldapsam_privates *ldap_state;
2247
2248 #ifdef WITH_LDAP_SAMCONFIG
2249         if (!location) {
2250                 int ldap_port = lp_ldap_port();
2251                         
2252                 /* remap default port if not using SSL (ie clear or TLS) */
2253                 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
2254                         ldap_port = 389;
2255                 }
2256
2257                 location = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
2258                 if (!location) {
2259                         return NT_STATUS_NO_MEMORY;
2260                 }
2261         }
2262 #endif
2263
2264         if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
2265                 return nt_status;
2266         }
2267
2268         (*pdb_method)->name = "ldapsam_compat";
2269
2270         ldap_state = (*pdb_method)->private_data;
2271         ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
2272
2273         sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
2274
2275         return NT_STATUS_OK;
2276 }
2277
2278 /**********************************************************************
2279  Initialise the normal mode for pdb_ldap
2280  *********************************************************************/
2281
2282 static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2283 {
2284         NTSTATUS nt_status;
2285         struct ldapsam_privates *ldap_state;
2286         uint32 alg_rid_base;
2287         pstring alg_rid_base_string;
2288         LDAPMessage *result = NULL;
2289         LDAPMessage *entry = NULL;
2290         DOM_SID ldap_domain_sid;
2291         DOM_SID secrets_domain_sid;
2292         pstring domain_sid_string;
2293
2294         if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
2295                 return nt_status;
2296         }
2297
2298         (*pdb_method)->name = "ldapsam";
2299
2300         ldap_state = (*pdb_method)->private_data;
2301         ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
2302
2303         /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
2304         
2305         nt_status = smbldap_search_domain_info(ldap_state->smbldap_state, &result, 
2306                 ldap_state->domain_name, True);
2307         
2308         if ( !NT_STATUS_IS_OK(nt_status) ) {
2309                 DEBUG(2, ("WARNING: Could not get domain info, nor add one to the domain\n"));
2310                 DEBUGADD(2, ("Continuing on regardless, will be unable to allocate new users/groups, "
2311                         "and will risk BDCs having inconsistant SIDs\n"));
2312                 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
2313                 return NT_STATUS_OK;
2314         }
2315
2316         /* Given that the above might fail, everything below this must be optional */
2317         
2318         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
2319         if (!entry) {
2320                 DEBUG(0, ("Could not get domain info entry\n"));
2321                 ldap_msgfree(result);
2322                 return NT_STATUS_UNSUCCESSFUL;
2323         }
2324
2325         if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
2326                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), 
2327                                  domain_sid_string)) 
2328         {
2329                 BOOL found_sid;
2330                 string_to_sid(&ldap_domain_sid, domain_sid_string);
2331                 found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid);
2332                 if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) {
2333                         /* reset secrets.tdb sid */
2334                         secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid);
2335                 }
2336                 sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
2337         }
2338
2339         if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
2340                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ALGORITHMIC_RID_BASE), 
2341                                  alg_rid_base_string)) 
2342         {
2343                 alg_rid_base = (uint32)atol(alg_rid_base_string);
2344                 if (alg_rid_base != algorithmic_rid_base()) {
2345                         DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n"
2346                                   "database was initialised.  Aborting. \n"));
2347                         ldap_msgfree(result);
2348                         return NT_STATUS_UNSUCCESSFUL;
2349                 }
2350         }
2351         ldap_msgfree(result);
2352
2353         return NT_STATUS_OK;
2354 }
2355
2356 NTSTATUS pdb_ldap_init(void)
2357 {
2358         NTSTATUS nt_status;
2359         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
2360                 return nt_status;
2361
2362         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
2363                 return nt_status;
2364
2365         return NT_STATUS_OK;
2366 }
2367
2368