r13389: get_ldap_filter is only used once, make it static
[samba.git] / source / passdb / pdb_ldap.c
1 /* 
2    Unix SMB/CIFS implementation.
3    LDAP protocol helper functions for SAMBA
4    Copyright (C) Jean François Micouleau        1998
5    Copyright (C) Gerald Carter                  2001-2003
6    Copyright (C) Shahms King                    2001
7    Copyright (C) Andrew Bartlett                2002-2003
8    Copyright (C) Stefan (metze) Metzmacher      2002-2003
9     
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23    
24 */
25
26 /* TODO:
27 *  persistent connections: if using NSS LDAP, many connections are made
28 *      however, using only one within Samba would be nice
29 *  
30 *  Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
31 *
32 *  Other LDAP based login attributes: accountExpires, etc.
33 *  (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
34 *  structures don't have fields for some of these attributes)
35 *
36 *  SSL is done, but can't get the certificate based authentication to work
37 *  against on my test platform (Linux 2.4, OpenLDAP 2.x)
38 */
39
40 /* NOTE: this will NOT work against an Active Directory server
41 *  due to the fact that the two password fields cannot be retrieved
42 *  from a server; recommend using security = domain in this situation
43 *  and/or winbind
44 */
45
46 #include "includes.h"
47
48 #undef DBGC_CLASS
49 #define DBGC_CLASS DBGC_PASSDB
50
51 #include <lber.h>
52 #include <ldap.h>
53
54 /*
55  * Work around versions of the LDAP client libs that don't have the OIDs
56  * defined, or have them defined under the old name.  
57  * This functionality is really a factor of the server, not the client 
58  *
59  */
60
61 #if defined(LDAP_EXOP_X_MODIFY_PASSWD) && !defined(LDAP_EXOP_MODIFY_PASSWD)
62 #define LDAP_EXOP_MODIFY_PASSWD LDAP_EXOP_X_MODIFY_PASSWD
63 #elif !defined(LDAP_EXOP_MODIFY_PASSWD)
64 #define LDAP_EXOP_MODIFY_PASSWD "1.3.6.1.4.1.4203.1.11.1"
65 #endif
66
67 #if defined(LDAP_EXOP_X_MODIFY_PASSWD_ID) && !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
68 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID LDAP_EXOP_X_MODIFY_PASSWD_ID
69 #elif !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
70 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID        ((ber_tag_t) 0x80U)
71 #endif
72
73 #if defined(LDAP_EXOP_X_MODIFY_PASSWD_NEW) && !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
74 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW LDAP_EXOP_X_MODIFY_PASSWD_NEW
75 #elif !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
76 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW       ((ber_tag_t) 0x82U)
77 #endif
78
79
80 #ifndef SAM_ACCOUNT
81 #define SAM_ACCOUNT struct sam_passwd
82 #endif
83
84 #include "smbldap.h"
85
86 /**********************************************************************
87  Simple helper function to make stuff better readable
88  **********************************************************************/
89
90 static LDAP *priv2ld(struct ldapsam_privates *priv)
91 {
92         return priv->smbldap_state->ldap_struct;
93 }
94
95 /**********************************************************************
96  Get the attribute name given a user schame version.
97  **********************************************************************/
98  
99 static const char* get_userattr_key2string( int schema_ver, int key )
100 {
101         switch ( schema_ver ) {
102                 case SCHEMAVER_SAMBAACCOUNT:
103                         return get_attr_key2string( attrib_map_v22, key );
104                         
105                 case SCHEMAVER_SAMBASAMACCOUNT:
106                         return get_attr_key2string( attrib_map_v30, key );
107                         
108                 default:
109                         DEBUG(0,("get_userattr_key2string: unknown schema version specified\n"));
110                         break;
111         }
112         return NULL;
113 }
114
115 /**********************************************************************
116  Return the list of attribute names given a user schema version.
117 **********************************************************************/
118
119 const char** get_userattr_list( TALLOC_CTX *mem_ctx, int schema_ver )
120 {
121         switch ( schema_ver ) {
122                 case SCHEMAVER_SAMBAACCOUNT:
123                         return get_attr_list( mem_ctx, attrib_map_v22 );
124                         
125                 case SCHEMAVER_SAMBASAMACCOUNT:
126                         return get_attr_list( mem_ctx, attrib_map_v30 );
127                 default:
128                         DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
129                         break;
130         }
131         
132         return NULL;
133 }
134
135 /**************************************************************************
136  Return the list of attribute names to delete given a user schema version.
137 **************************************************************************/
138
139 static const char** get_userattr_delete_list( TALLOC_CTX *mem_ctx,
140                                               int schema_ver )
141 {
142         switch ( schema_ver ) {
143                 case SCHEMAVER_SAMBAACCOUNT:
144                         return get_attr_list( mem_ctx,
145                                               attrib_map_to_delete_v22 );
146                         
147                 case SCHEMAVER_SAMBASAMACCOUNT:
148                         return get_attr_list( mem_ctx,
149                                               attrib_map_to_delete_v30 );
150                 default:
151                         DEBUG(0,("get_userattr_delete_list: unknown schema version specified!\n"));
152                         break;
153         }
154         
155         return NULL;
156 }
157
158
159 /*******************************************************************
160  Generate the LDAP search filter for the objectclass based on the 
161  version of the schema we are using.
162 ******************************************************************/
163
164 static const char* get_objclass_filter( int schema_ver )
165 {
166         static fstring objclass_filter;
167         
168         switch( schema_ver ) {
169                 case SCHEMAVER_SAMBAACCOUNT:
170                         fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT );
171                         break;
172                 case SCHEMAVER_SAMBASAMACCOUNT:
173                         fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT );
174                         break;
175                 default:
176                         DEBUG(0,("get_objclass_filter: Invalid schema version specified!\n"));
177                         break;
178         }
179         
180         return objclass_filter; 
181 }
182
183 /*****************************************************************
184  Scan a sequence number off OpenLDAP's syncrepl contextCSN
185 ******************************************************************/
186
187 static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_num)
188 {
189         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
190         NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
191         LDAPMessage *msg = NULL;
192         LDAPMessage *entry = NULL;
193         TALLOC_CTX *mem_ctx;
194         char **values = NULL;
195         int rc, num_result, num_values, rid;
196         pstring suffix;
197         fstring tok;
198         const char *p;
199         const char **attrs;
200
201         /* Unfortunatly there is no proper way to detect syncrepl-support in
202          * smbldap_connect_system(). The syncrepl OIDs are submitted for publication
203          * but do not show up in the root-DSE yet. Neither we can query the
204          * subschema-context for the syncProviderSubentry or syncConsumerSubentry
205          * objectclass. Currently we require lp_ldap_suffix() to show up as
206          * namingContext.  -  Guenther
207          */
208
209         if (!lp_parm_bool(-1, "ldapsam", "syncrepl_seqnum", False)) {
210                 return ntstatus;
211         }
212
213         if (!seq_num) {
214                 DEBUG(3,("ldapsam_get_seq_num: no sequence_number\n"));
215                 return ntstatus;
216         }
217
218         if (!smbldap_has_naming_context(ldap_state->smbldap_state, lp_ldap_suffix())) {
219                 DEBUG(3,("ldapsam_get_seq_num: DIT not configured to hold %s "
220                          "as top-level namingContext\n", lp_ldap_suffix()));
221                 return ntstatus;
222         }
223
224         mem_ctx = talloc_init("ldapsam_get_seq_num");
225
226         if (mem_ctx == NULL)
227                 return NT_STATUS_NO_MEMORY;
228
229         attrs = TALLOC_ARRAY(mem_ctx, const char *, 2);
230
231         /* if we got a syncrepl-rid (up to three digits long) we speak with a consumer */
232         rid = lp_parm_int(-1, "ldapsam", "syncrepl_rid", -1);
233         if (rid > 0) {
234
235                 /* consumer syncreplCookie: */
236                 /* csn=20050126161620Z#0000001#00#00000 */
237                 attrs[0] = talloc_strdup(mem_ctx, "syncreplCookie");
238                 attrs[1] = NULL;
239                 pstr_sprintf( suffix, "cn=syncrepl%d,%s", rid, lp_ldap_suffix());
240
241         } else {
242
243                 /* provider contextCSN */
244                 /* 20050126161620Z#000009#00#000000 */
245                 attrs[0] = talloc_strdup(mem_ctx, "contextCSN");
246                 attrs[1] = NULL;
247                 pstr_sprintf( suffix, "cn=ldapsync,%s", lp_ldap_suffix());
248
249         }
250
251         rc = smbldap_search(ldap_state->smbldap_state, suffix,
252                             LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &msg);
253
254         if (rc != LDAP_SUCCESS) {
255                 goto done;
256         }
257
258         num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg);
259         if (num_result != 1) {
260                 DEBUG(3,("ldapsam_get_seq_num: Expected one entry, got %d\n", num_result));
261                 goto done;
262         }
263
264         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg);
265         if (entry == NULL) {
266                 DEBUG(3,("ldapsam_get_seq_num: Could not retrieve entry\n"));
267                 goto done;
268         }
269
270         values = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, attrs[0]);
271         if (values == NULL) {
272                 DEBUG(3,("ldapsam_get_seq_num: no values\n"));
273                 goto done;
274         }
275
276         num_values = ldap_count_values(values);
277         if (num_values == 0) {
278                 DEBUG(3,("ldapsam_get_seq_num: not a single value\n"));
279                 goto done;
280         }
281
282         p = values[0];
283         if (!next_token(&p, tok, "#", sizeof(tok))) {
284                 DEBUG(0,("ldapsam_get_seq_num: failed to parse sequence number\n"));
285                 goto done;
286         }
287
288         p = tok;
289         if (!strncmp(p, "csn=", strlen("csn=")))
290                 p += strlen("csn=");
291
292         DEBUG(10,("ldapsam_get_seq_num: got %s: %s\n", attrs[0], p));
293
294         *seq_num = generalized_to_unix_time(p);
295
296         /* very basic sanity check */
297         if (*seq_num <= 0) {
298                 DEBUG(3,("ldapsam_get_seq_num: invalid sequence number: %d\n", 
299                         (int)*seq_num));
300                 goto done;
301         }
302
303         ntstatus = NT_STATUS_OK;
304
305  done:
306         if (values != NULL)
307                 ldap_value_free(values);
308         if (msg != NULL)
309                 ldap_msgfree(msg);
310         if (mem_ctx)
311                 talloc_destroy(mem_ctx);
312
313         return ntstatus;
314 }
315
316 /*******************************************************************
317  Run the search by name.
318 ******************************************************************/
319
320 int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state, 
321                                           const char *user,
322                                           LDAPMessage ** result,
323                                           const char **attr)
324 {
325         pstring filter;
326         char *escape_user = escape_ldap_string_alloc(user);
327
328         if (!escape_user) {
329                 return LDAP_NO_MEMORY;
330         }
331
332         /*
333          * in the filter expression, replace %u with the real name
334          * so in ldap filter, %u MUST exist :-)
335          */
336         pstr_sprintf(filter, "(&%s%s)", "(uid=%u)", 
337                 get_objclass_filter(ldap_state->schema_ver));
338
339         /* 
340          * have to use this here because $ is filtered out
341            * in pstring_sub
342          */
343         
344
345         all_string_sub(filter, "%u", escape_user, sizeof(pstring));
346         SAFE_FREE(escape_user);
347
348         return smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result);
349 }
350
351 /*******************************************************************
352  Run the search by rid.
353 ******************************************************************/
354
355 static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, 
356                                          uint32 rid, LDAPMessage ** result, 
357                                          const char **attr)
358 {
359         pstring filter;
360         int rc;
361
362         pstr_sprintf(filter, "(&(rid=%i)%s)", rid, 
363                 get_objclass_filter(ldap_state->schema_ver));
364         
365         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result);
366         
367         return rc;
368 }
369
370 /*******************************************************************
371  Run the search by SID.
372 ******************************************************************/
373
374 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, 
375                                          const DOM_SID *sid, LDAPMessage ** result, 
376                                          const char **attr)
377 {
378         pstring filter;
379         int rc;
380         fstring sid_string;
381
382         pstr_sprintf(filter, "(&(%s=%s)%s)", 
383                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
384                 sid_to_string(sid_string, sid), 
385                 get_objclass_filter(ldap_state->schema_ver));
386                 
387         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result);
388         
389         return rc;
390 }
391
392 /*******************************************************************
393  Delete complete object or objectclass and attrs from
394  object found in search_result depending on lp_ldap_delete_dn
395 ******************************************************************/
396
397 static int ldapsam_delete_entry(struct ldapsam_privates *priv,
398                                 TALLOC_CTX *mem_ctx,
399                                 LDAPMessage *entry,
400                                 const char *objectclass,
401                                 const char **attrs)
402 {
403         LDAPMod **mods = NULL;
404         char *name;
405         const char *dn;
406         BerElement *ptr = NULL;
407
408         dn = smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry);
409         if (dn == NULL) {
410                 return LDAP_NO_MEMORY;
411         }
412
413         if (lp_ldap_delete_dn()) {
414                 return smbldap_delete(priv->smbldap_state, dn);
415         }
416
417         /* Ok, delete only the SAM attributes */
418         
419         for (name = ldap_first_attribute(priv2ld(priv), entry, &ptr);
420              name != NULL;
421              name = ldap_next_attribute(priv2ld(priv), entry, ptr)) {
422                 const char **attrib;
423
424                 /* We are only allowed to delete the attributes that
425                    really exist. */
426
427                 for (attrib = attrs; *attrib != NULL; attrib++) {
428                         if (strequal(*attrib, name)) {
429                                 DEBUG(10, ("ldapsam_delete_entry: deleting "
430                                            "attribute %s\n", name));
431                                 smbldap_set_mod(&mods, LDAP_MOD_DELETE, name,
432                                                 NULL);
433                         }
434                 }
435                 ldap_memfree(name);
436         }
437
438         if (ptr != NULL) {
439                 ber_free(ptr, 0);
440         }
441         
442         smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
443         talloc_autofree_ldapmod(mem_ctx, mods);
444         
445         return smbldap_modify(priv->smbldap_state, dn, mods);
446 }
447                   
448 /* New Interface is being implemented here */
449
450 #if 0   /* JERRY - not uesed anymore */
451
452 /**********************************************************************
453 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
454 *********************************************************************/
455 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, 
456                                 SAM_ACCOUNT * sampass,
457                                 LDAPMessage * entry,
458                                 gid_t *gid)
459 {
460         pstring  homedir;
461         pstring  temp;
462         char **ldap_values;
463         char **values;
464
465         if ((ldap_values = ldap_get_values (ldap_state->smbldap_state->ldap_struct, entry, "objectClass")) == NULL) {
466                 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
467                 return False;
468         }
469
470         for (values=ldap_values;*values;values++) {
471                 if (strequal(*values, LDAP_OBJ_POSIXACCOUNT )) {
472                         break;
473                 }
474         }
475         
476         if (!*values) { /*end of array, no posixAccount */
477                 DEBUG(10, ("user does not have %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
478                 ldap_value_free(ldap_values);
479                 return False;
480         }
481         ldap_value_free(ldap_values);
482
483         if ( !smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
484                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_UNIX_HOME), homedir) ) 
485         {
486                 return False;
487         }
488         
489         if ( !smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
490                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_GIDNUMBER), temp) )
491         {
492                 return False;
493         }
494         
495         *gid = (gid_t)atol(temp);
496
497         pdb_set_unix_homedir(sampass, homedir, PDB_SET);
498         
499         DEBUG(10, ("user has %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
500         
501         return True;
502 }
503
504 #endif
505
506 static time_t ldapsam_get_entry_timestamp(
507         struct ldapsam_privates *ldap_state,
508         LDAPMessage * entry)
509 {
510         pstring temp;   
511         struct tm tm;
512
513         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
514                         get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP),
515                         temp))
516                 return (time_t) 0;
517
518         strptime(temp, "%Y%m%d%H%M%SZ", &tm);
519         tzset();
520         return timegm(&tm);
521 }
522
523 /**********************************************************************
524  Initialize SAM_ACCOUNT from an LDAP query.
525  (Based on init_sam_from_buffer in pdb_tdb.c)
526 *********************************************************************/
527
528 static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state, 
529                                 SAM_ACCOUNT * sampass,
530                                 LDAPMessage * entry)
531 {
532         time_t  logon_time,
533                         logoff_time,
534                         kickoff_time,
535                         pass_last_set_time, 
536                         pass_can_change_time, 
537                         pass_must_change_time,
538                         ldap_entry_time,
539                         bad_password_time;
540         pstring         username, 
541                         domain,
542                         nt_username,
543                         fullname,
544                         homedir,
545                         dir_drive,
546                         logon_script,
547                         profile_path,
548                         acct_desc,
549                         workstations;
550         char            munged_dial[2048];
551         uint32          user_rid; 
552         uint8           smblmpwd[LM_HASH_LEN],
553                         smbntpwd[NT_HASH_LEN];
554         BOOL            use_samba_attrs = True;
555         uint16          acct_ctrl = 0, 
556                         logon_divs;
557         uint16          bad_password_count = 0, 
558                         logon_count = 0;
559         uint32 hours_len;
560         uint8           hours[MAX_HOURS_LEN];
561         pstring temp;
562         LOGIN_CACHE     *cache_entry = NULL;
563         uint32          pwHistLen;
564         pstring         tmpstring;
565         BOOL expand_explicit = lp_passdb_expand_explicit();
566
567         /*
568          * do a little initialization
569          */
570         username[0]     = '\0';
571         domain[0]       = '\0';
572         nt_username[0]  = '\0';
573         fullname[0]     = '\0';
574         homedir[0]      = '\0';
575         dir_drive[0]    = '\0';
576         logon_script[0] = '\0';
577         profile_path[0] = '\0';
578         acct_desc[0]    = '\0';
579         munged_dial[0]  = '\0';
580         workstations[0] = '\0';
581          
582
583         if (sampass == NULL || ldap_state == NULL || entry == NULL) {
584                 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
585                 return False;
586         }
587
588         if (priv2ld(ldap_state) == NULL) {
589                 DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->"
590                           "ldap_struct is NULL!\n"));
591                 return False;
592         }
593         
594         if (!smbldap_get_single_pstring(priv2ld(ldap_state), entry, "uid",
595                                         username)) {
596                 DEBUG(1, ("init_sam_from_ldap: No uid attribute found for "
597                           "this user!\n"));
598                 return False;
599         }
600
601         DEBUG(2, ("init_sam_from_ldap: Entry found for user: %s\n", username));
602
603         pstrcpy(nt_username, username);
604
605         pstrcpy(domain, ldap_state->domain_name);
606         
607         pdb_set_username(sampass, username, PDB_SET);
608
609         pdb_set_domain(sampass, domain, PDB_DEFAULT);
610         pdb_set_nt_username(sampass, nt_username, PDB_SET);
611
612         /* deal with different attributes between the schema first */
613         
614         if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ) {
615                 if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
616                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp)) {
617                         pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
618                 }
619                 
620                 if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
621                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp)) {
622                         pdb_set_group_sid_from_string(sampass, temp, PDB_SET);                  
623                 } else {
624                         pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
625                 }
626         } else {
627                 if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
628                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp)) {
629                         user_rid = (uint32)atol(temp);
630                         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
631                 }
632                 
633                 if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
634                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp)) {
635                         pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
636                 } else {
637                         uint32 group_rid;
638                         
639                         group_rid = (uint32)atol(temp);
640                         
641                         /* for some reason, we often have 0 as a primary group RID.
642                            Make sure that we treat this just as a 'default' value */
643                            
644                         if ( group_rid > 0 )
645                                 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
646                         else
647                                 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
648                 }
649         }
650
651         if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
652                 DEBUG(1, ("init_sam_from_ldap: no %s or %s attribute found for this user %s\n", 
653                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
654                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID),
655                         username));
656                 return False;
657         }
658
659         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
660                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp)) {
661                 /* leave as default */
662         } else {
663                 pass_last_set_time = (time_t) atol(temp);
664                 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
665         }
666
667         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
668                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp)) {
669                 /* leave as default */
670         } else {
671                 logon_time = (time_t) atol(temp);
672                 pdb_set_logon_time(sampass, logon_time, PDB_SET);
673         }
674
675         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
676                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp)) {
677                 /* leave as default */
678         } else {
679                 logoff_time = (time_t) atol(temp);
680                 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
681         }
682
683         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
684                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp)) {
685                 /* leave as default */
686         } else {
687                 kickoff_time = (time_t) atol(temp);
688                 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
689         }
690
691         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
692                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp)) {
693                 /* leave as default */
694         } else {
695                 pass_can_change_time = (time_t) atol(temp);
696                 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
697         }
698
699         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
700                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp)) {    
701                 /* leave as default */
702         } else {
703                 pass_must_change_time = (time_t) atol(temp);
704                 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
705         }
706
707         /* recommend that 'gecos' and 'displayName' should refer to the same
708          * attribute OID.  userFullName depreciated, only used by Samba
709          * primary rules of LDAP: don't make a new attribute when one is already defined
710          * that fits your needs; using cn then displayName rather than 'userFullName'
711          */
712
713         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
714                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), fullname)) {
715                 if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
716                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_CN), fullname)) {
717                         /* leave as default */
718                 } else {
719                         pdb_set_fullname(sampass, fullname, PDB_SET);
720                 }
721         } else {
722                 pdb_set_fullname(sampass, fullname, PDB_SET);
723         }
724
725         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
726                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive)) 
727         {
728                 pdb_set_dir_drive( sampass, lp_logon_drive(), PDB_DEFAULT );
729         } else {
730                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
731         }
732
733         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
734                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir)) 
735         {
736                 pdb_set_homedir( sampass, 
737                         talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()),
738                         PDB_DEFAULT );
739         } else {
740                 pstrcpy( tmpstring, homedir );
741                 if (expand_explicit) {
742                         standard_sub_basic( username, tmpstring,
743                                             sizeof(tmpstring) );
744                 }
745                 pdb_set_homedir(sampass, tmpstring, PDB_SET);
746         }
747
748         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
749                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script)) 
750         {
751                 pdb_set_logon_script( sampass, 
752                         talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()), 
753                         PDB_DEFAULT );
754         } else {
755                 pstrcpy( tmpstring, logon_script );
756                 if (expand_explicit) {
757                         standard_sub_basic( username, tmpstring,
758                                             sizeof(tmpstring) );
759                 }
760                 pdb_set_logon_script(sampass, tmpstring, PDB_SET);
761         }
762
763         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
764                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path)) 
765         {
766                 pdb_set_profile_path( sampass, 
767                         talloc_sub_basic( sampass->mem_ctx, username, lp_logon_path()),
768                         PDB_DEFAULT );
769         } else {
770                 pstrcpy( tmpstring, profile_path );
771                 if (expand_explicit) {
772                         standard_sub_basic( username, tmpstring,
773                                             sizeof(tmpstring) );
774                 }
775                 pdb_set_profile_path(sampass, tmpstring, PDB_SET);
776         }
777
778         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
779                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), acct_desc)) 
780         {
781                 /* leave as default */
782         } else {
783                 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
784         }
785
786         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
787                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), workstations)) {
788                 /* leave as default */;
789         } else {
790                 pdb_set_workstations(sampass, workstations, PDB_SET);
791         }
792
793         if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
794                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MUNGED_DIAL), munged_dial, sizeof(munged_dial))) {
795                 /* leave as default */;
796         } else {
797                 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
798         }
799         
800         /* FIXME: hours stuff should be cleaner */
801         
802         logon_divs = 168;
803         hours_len = 21;
804         memset(hours, 0xff, hours_len);
805
806         if (ldap_state->is_nds_ldap) {
807                 char *user_dn;
808                 size_t pwd_len;
809                 char clear_text_pw[512];
810    
811                 /* Make call to Novell eDirectory ldap extension to get clear text password.
812                         NOTE: This will only work if we have an SSL connection to eDirectory. */
813                 user_dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
814                 if (user_dn != NULL) {
815                         DEBUG(3, ("init_sam_from_ldap: smbldap_get_dn(%s) returned '%s'\n", username, user_dn));
816
817                         pwd_len = sizeof(clear_text_pw);
818                         if (pdb_nds_get_password(ldap_state->smbldap_state, user_dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) {
819                                 nt_lm_owf_gen(clear_text_pw, smbntpwd, smblmpwd);
820                                 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
821                                         return False;
822                                 ZERO_STRUCT(smblmpwd);
823                                 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
824                                         return False;
825                                 ZERO_STRUCT(smbntpwd);
826                                 use_samba_attrs = False;
827                         }
828                 } else {
829                         DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username));
830                 }
831         }
832
833         if (use_samba_attrs) {
834                 if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, 
835                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) {
836                         /* leave as default */
837                 } else {
838                         pdb_gethexpwd(temp, smblmpwd);
839                         memset((char *)temp, '\0', strlen(temp)+1);
840                         if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
841                                 return False;
842                         ZERO_STRUCT(smblmpwd);
843                 }
844
845                 if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
846                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) {
847                         /* leave as default */
848                 } else {
849                         pdb_gethexpwd(temp, smbntpwd);
850                         memset((char *)temp, '\0', strlen(temp)+1);
851                         if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
852                                 return False;
853                         ZERO_STRUCT(smbntpwd);
854                 }
855         }
856
857         pwHistLen = 0;
858
859         pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
860         if (pwHistLen > 0){
861                 uint8 *pwhist = NULL;
862                 int i;
863
864                 /* We can only store (sizeof(pstring)-1)/64 password history entries. */
865                 pwHistLen = MIN(pwHistLen, ((sizeof(temp)-1)/64));
866
867                 if ((pwhist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){
868                         DEBUG(0, ("init_sam_from_ldap: malloc failed!\n"));
869                         return False;
870                 }
871                 memset(pwhist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
872
873                 if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, 
874                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY), temp)) {
875                         /* leave as default - zeros */
876                 } else {
877                         BOOL hex_failed = False;
878                         for (i = 0; i < pwHistLen; i++){
879                                 /* Get the 16 byte salt. */
880                                 if (!pdb_gethexpwd(&temp[i*64], &pwhist[i*PW_HISTORY_ENTRY_LEN])) {
881                                         hex_failed = True;
882                                         break;
883                                 }
884                                 /* Get the 16 byte MD5 hash of salt+passwd. */
885                                 if (!pdb_gethexpwd(&temp[(i*64)+32],
886                                                 &pwhist[(i*PW_HISTORY_ENTRY_LEN)+PW_HISTORY_SALT_LEN])) {
887                                         hex_failed = True;
888                                         break;
889                                 }
890                         }
891                         if (hex_failed) {
892                                 DEBUG(0,("init_sam_from_ldap: Failed to get password history for user %s\n",
893                                         username));
894                                 memset(pwhist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
895                         }
896                 }
897                 if (!pdb_set_pw_history(sampass, pwhist, pwHistLen, PDB_SET)){
898                         SAFE_FREE(pwhist);
899                         return False;
900                 }
901                 SAFE_FREE(pwhist);
902         }
903
904         if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
905                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp)) {
906                 acct_ctrl |= ACB_NORMAL;
907         } else {
908                 acct_ctrl = pdb_decode_acct_ctrl(temp);
909
910                 if (acct_ctrl == 0)
911                         acct_ctrl |= ACB_NORMAL;
912
913                 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
914         }
915
916         pdb_set_hours_len(sampass, hours_len, PDB_SET);
917         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
918
919         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
920                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_BAD_PASSWORD_COUNT), temp)) {
921                         /* leave as default */
922         } else {
923                 bad_password_count = (uint32) atol(temp);
924                 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
925         }
926
927         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
928                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_BAD_PASSWORD_TIME), temp)) {
929                 /* leave as default */
930         } else {
931                 bad_password_time = (time_t) atol(temp);
932                 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
933         }
934
935
936         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
937                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_COUNT), temp)) {
938                         /* leave as default */
939         } else {
940                 logon_count = (uint32) atol(temp);
941                 pdb_set_logon_count(sampass, logon_count, PDB_SET);
942         }
943
944         /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
945
946         if(!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
947                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_HOURS), temp)) {
948                         /* leave as default */
949         } else {
950                 pdb_gethexhours(temp, hours);
951                 memset((char *)temp, '\0', strlen(temp) +1);
952                 pdb_set_hours(sampass, hours, PDB_SET);
953                 ZERO_STRUCT(hours);
954         }
955
956         if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
957                 if (smbldap_get_single_pstring(priv2ld(ldap_state), entry,
958                                                "uidNumber", temp)) {
959                         /* We've got a uid, feed the cache */
960                         uid_t uid = strtoul(temp, NULL, 10);
961                         store_uid_sid_cache(pdb_get_user_sid(sampass), uid);
962                 }
963         }
964
965         /* check the timestamp of the cache vs ldap entry */
966         if (!(ldap_entry_time = ldapsam_get_entry_timestamp(ldap_state, 
967                                                             entry)))
968                 return True;
969
970         /* see if we have newer updates */
971         if (!(cache_entry = login_cache_read(sampass))) {
972                 DEBUG (9, ("No cache entry, bad count = %u, bad time = %u\n",
973                            (unsigned int)pdb_get_bad_password_count(sampass),
974                            (unsigned int)pdb_get_bad_password_time(sampass)));
975                 return True;
976         }
977
978         DEBUG(7, ("ldap time is %u, cache time is %u, bad time = %u\n", 
979                   (unsigned int)ldap_entry_time, (unsigned int)cache_entry->entry_timestamp, 
980                   (unsigned int)cache_entry->bad_password_time));
981
982         if (ldap_entry_time > cache_entry->entry_timestamp) {
983                 /* cache is older than directory , so
984                    we need to delete the entry but allow the 
985                    fields to be written out */
986                 login_cache_delentry(sampass);
987         } else {
988                 /* read cache in */
989                 pdb_set_acct_ctrl(sampass, 
990                                   pdb_get_acct_ctrl(sampass) | 
991                                   (cache_entry->acct_ctrl & ACB_AUTOLOCK),
992                                   PDB_SET);
993                 pdb_set_bad_password_count(sampass, 
994                                            cache_entry->bad_password_count, 
995                                            PDB_SET);
996                 pdb_set_bad_password_time(sampass, 
997                                           cache_entry->bad_password_time, 
998                                           PDB_SET);
999         }
1000
1001         SAFE_FREE(cache_entry);
1002         return True;
1003 }
1004
1005 /**********************************************************************
1006  Initialize the ldap db from a SAM_ACCOUNT. Called on update.
1007  (Based on init_buffer_from_sam in pdb_tdb.c)
1008 *********************************************************************/
1009
1010 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, 
1011                                 LDAPMessage *existing,
1012                                 LDAPMod *** mods, SAM_ACCOUNT * sampass,
1013                                 BOOL (*need_update)(const SAM_ACCOUNT *,
1014                                                     enum pdb_elements))
1015 {
1016         pstring temp;
1017         uint32 rid;
1018
1019         if (mods == NULL || sampass == NULL) {
1020                 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1021                 return False;
1022         }
1023
1024         *mods = NULL;
1025
1026         /* 
1027          * took out adding "objectclass: sambaAccount"
1028          * do this on a per-mod basis
1029          */
1030         if (need_update(sampass, PDB_USERNAME))
1031                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, 
1032                               "uid", pdb_get_username(sampass));
1033
1034         DEBUG(2, ("init_ldap_from_sam: Setting entry for user: %s\n", pdb_get_username(sampass)));
1035
1036         /* only update the RID if we actually need to */
1037         if (need_update(sampass, PDB_USERSID)) {
1038                 fstring sid_string;
1039                 fstring dom_sid_string;
1040                 const DOM_SID *user_sid = pdb_get_user_sid(sampass);
1041                 
1042                 switch ( ldap_state->schema_ver ) {
1043                         case SCHEMAVER_SAMBAACCOUNT:
1044                                 if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) {
1045                                         DEBUG(1, ("init_ldap_from_sam: User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", 
1046                                                 sid_to_string(sid_string, user_sid), 
1047                                                 sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
1048                                         return False;
1049                                 }
1050                                 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1051                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1052                                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), 
1053                                         temp);
1054                                 break;
1055                                 
1056                         case SCHEMAVER_SAMBASAMACCOUNT:
1057                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1058                                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), 
1059                                         sid_to_string(sid_string, user_sid));                                 
1060                                 break;
1061                                 
1062                         default:
1063                                 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
1064                                 break;
1065                 }               
1066         }
1067
1068         /* we don't need to store the primary group RID - so leaving it
1069            'free' to hang off the unix primary group makes life easier */
1070
1071         if (need_update(sampass, PDB_GROUPSID)) {
1072                 fstring sid_string;
1073                 fstring dom_sid_string;
1074                 const DOM_SID *group_sid = pdb_get_group_sid(sampass);
1075                 
1076                 switch ( ldap_state->schema_ver ) {
1077                         case SCHEMAVER_SAMBAACCOUNT:
1078                                 if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) {
1079                                         DEBUG(1, ("init_ldap_from_sam: User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
1080                                                 sid_to_string(sid_string, group_sid),
1081                                                 sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
1082                                         return False;
1083                                 }
1084
1085                                 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1086                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1087                                         get_userattr_key2string(ldap_state->schema_ver, 
1088                                         LDAP_ATTR_PRIMARY_GROUP_RID), temp);
1089                                 break;
1090                                 
1091                         case SCHEMAVER_SAMBASAMACCOUNT:
1092                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1093                                         get_userattr_key2string(ldap_state->schema_ver, 
1094                                         LDAP_ATTR_PRIMARY_GROUP_SID), sid_to_string(sid_string, group_sid));
1095                                 break;
1096                                 
1097                         default:
1098                                 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
1099                                 break;
1100                 }
1101                 
1102         }
1103         
1104         /* displayName, cn, and gecos should all be the same
1105          *  most easily accomplished by giving them the same OID
1106          *  gecos isn't set here b/c it should be handled by the 
1107          *  add-user script
1108          *  We change displayName only and fall back to cn if
1109          *  it does not exist.
1110          */
1111
1112         if (need_update(sampass, PDB_FULLNAME))
1113                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1114                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), 
1115                         pdb_get_fullname(sampass));
1116
1117         if (need_update(sampass, PDB_ACCTDESC))
1118                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1119                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), 
1120                         pdb_get_acct_desc(sampass));
1121
1122         if (need_update(sampass, PDB_WORKSTATIONS))
1123                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1124                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), 
1125                         pdb_get_workstations(sampass));
1126         
1127         if (need_update(sampass, PDB_MUNGEDDIAL))
1128                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1129                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MUNGED_DIAL), 
1130                         pdb_get_munged_dial(sampass));
1131         
1132         if (need_update(sampass, PDB_SMBHOME))
1133                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1134                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), 
1135                         pdb_get_homedir(sampass));
1136                         
1137         if (need_update(sampass, PDB_DRIVE))
1138                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1139                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), 
1140                         pdb_get_dir_drive(sampass));
1141
1142         if (need_update(sampass, PDB_LOGONSCRIPT))
1143                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1144                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), 
1145                         pdb_get_logon_script(sampass));
1146
1147         if (need_update(sampass, PDB_PROFILE))
1148                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1149                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), 
1150                         pdb_get_profile_path(sampass));
1151
1152         slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
1153         if (need_update(sampass, PDB_LOGONTIME))
1154                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1155                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp);
1156
1157         slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
1158         if (need_update(sampass, PDB_LOGOFFTIME))
1159                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1160                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp);
1161
1162         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
1163         if (need_update(sampass, PDB_KICKOFFTIME))
1164                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1165                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
1166
1167         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
1168         if (need_update(sampass, PDB_CANCHANGETIME))
1169                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1170                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
1171
1172         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
1173         if (need_update(sampass, PDB_MUSTCHANGETIME))
1174                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1175                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp);
1176
1177
1178         if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))
1179                         || (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
1180
1181                 if (need_update(sampass, PDB_LMPASSWD)) {
1182                         const uchar *lm_pw =  pdb_get_lanman_passwd(sampass);
1183                         if (lm_pw) {
1184                                 pdb_sethexpwd(temp, lm_pw,
1185                                               pdb_get_acct_ctrl(sampass));
1186                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1187                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), 
1188                                                  temp);
1189                         } else {
1190                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1191                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), 
1192                                                  NULL);
1193                         }
1194                 }
1195                 if (need_update(sampass, PDB_NTPASSWD)) {
1196                         const uchar *nt_pw =  pdb_get_nt_passwd(sampass);
1197                         if (nt_pw) {
1198                                 pdb_sethexpwd(temp, nt_pw,
1199                                               pdb_get_acct_ctrl(sampass));
1200                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1201                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), 
1202                                                  temp);
1203                         } else {
1204                                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1205                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), 
1206                                                  NULL);
1207                         }
1208                 }
1209
1210                 if (need_update(sampass, PDB_PWHISTORY)) {
1211                         uint32 pwHistLen = 0;
1212                         pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1213                         if (pwHistLen == 0) {
1214                                 /* Remove any password history from the LDAP store. */
1215                                 memset(temp, '0', 64); /* NOTE !!!! '0' *NOT '\0' */
1216                                 temp[64] = '\0';
1217                         } else {
1218                                 int i; 
1219                                 uint32 currHistLen = 0;
1220                                 const uint8 *pwhist = pdb_get_pw_history(sampass, &currHistLen);
1221                                 if (pwhist != NULL) {
1222                                         /* We can only store (sizeof(pstring)-1)/64 password history entries. */
1223                                         pwHistLen = MIN(pwHistLen, ((sizeof(temp)-1)/64));
1224                                         for (i=0; i< pwHistLen && i < currHistLen; i++) {
1225                                                 /* Store the salt. */
1226                                                 pdb_sethexpwd(&temp[i*64], &pwhist[i*PW_HISTORY_ENTRY_LEN], 0);
1227                                                 /* Followed by the md5 hash of salt + md4 hash */
1228                                                 pdb_sethexpwd(&temp[(i*64)+32],
1229                                                         &pwhist[(i*PW_HISTORY_ENTRY_LEN)+PW_HISTORY_SALT_LEN], 0);
1230                                                 DEBUG(100, ("temp=%s\n", temp));
1231                                         }
1232                                 } 
1233                         }
1234                         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1235                                          get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY), 
1236                                          temp);
1237                 }
1238
1239                 if (need_update(sampass, PDB_PASSLASTSET)) {
1240                         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
1241                         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1242                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), 
1243                                 temp);
1244                 }
1245         }
1246
1247         if (need_update(sampass, PDB_HOURS)) {
1248                 const uint8 *hours = pdb_get_hours(sampass);
1249                 if (hours) {
1250                         pdb_sethexhours(temp, hours);
1251                         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct,
1252                                 existing,
1253                                 mods,
1254                                 get_userattr_key2string(ldap_state->schema_ver,
1255                                                 LDAP_ATTR_LOGON_HOURS),
1256                                 temp);
1257                 }
1258         }
1259
1260         if (need_update(sampass, PDB_ACCTCTRL))
1261                 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1262                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), 
1263                         pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), NEW_PW_FORMAT_SPACE_PADDED_LEN));
1264
1265         /* password lockout cache: 
1266            - If we are now autolocking or clearing, we write to ldap
1267            - If we are clearing, we delete the cache entry
1268            - If the count is > 0, we update the cache
1269
1270            This even means when autolocking, we cache, just in case the
1271            update doesn't work, and we have to cache the autolock flag */
1272
1273         if (need_update(sampass, PDB_BAD_PASSWORD_COUNT))  /* &&
1274             need_update(sampass, PDB_BAD_PASSWORD_TIME)) */ {
1275                 uint16 badcount = pdb_get_bad_password_count(sampass);
1276                 time_t badtime = pdb_get_bad_password_time(sampass);
1277                 uint32 pol;
1278                 pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &pol);
1279
1280                 DEBUG(3, ("updating bad password fields, policy=%u, count=%u, time=%u\n",
1281                         (unsigned int)pol, (unsigned int)badcount, (unsigned int)badtime));
1282
1283                 if ((badcount >= pol) || (badcount == 0)) {
1284                         DEBUG(7, ("making mods to update ldap, count=%u, time=%u\n",
1285                                 (unsigned int)badcount, (unsigned int)badtime));
1286                         slprintf (temp, sizeof (temp) - 1, "%li", (long)badcount);
1287                         smbldap_make_mod(
1288                                 ldap_state->smbldap_state->ldap_struct,
1289                                 existing, mods, 
1290                                 get_userattr_key2string(
1291                                         ldap_state->schema_ver, 
1292                                         LDAP_ATTR_BAD_PASSWORD_COUNT),
1293                                 temp);
1294
1295                         slprintf (temp, sizeof (temp) - 1, "%li", badtime);
1296                         smbldap_make_mod(
1297                                 ldap_state->smbldap_state->ldap_struct, 
1298                                 existing, mods,
1299                                 get_userattr_key2string(
1300                                         ldap_state->schema_ver, 
1301                                         LDAP_ATTR_BAD_PASSWORD_TIME), 
1302                                 temp);
1303                 }
1304                 if (badcount == 0) {
1305                         DEBUG(7, ("bad password count is reset, deleting login cache entry for %s\n", pdb_get_nt_username(sampass)));
1306                         login_cache_delentry(sampass);
1307                 } else {
1308                         LOGIN_CACHE cache_entry;
1309
1310                         cache_entry.entry_timestamp = time(NULL);
1311                         cache_entry.acct_ctrl = pdb_get_acct_ctrl(sampass);
1312                         cache_entry.bad_password_count = badcount;
1313                         cache_entry.bad_password_time = badtime;
1314
1315                         DEBUG(7, ("Updating bad password count and time in login cache\n"));
1316                         login_cache_write(sampass, cache_entry);
1317                 }
1318         }
1319
1320         return True;
1321 }
1322
1323 /**********************************************************************
1324  Connect to LDAP server for password enumeration.
1325 *********************************************************************/
1326
1327 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint16 acb_mask)
1328 {
1329         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1330         int rc;
1331         pstring filter, suffix;
1332         const char **attr_list;
1333         BOOL machine_mask = False, user_mask = False;
1334
1335         pstr_sprintf( filter, "(&%s%s)", "(uid=%u)", 
1336                 get_objclass_filter(ldap_state->schema_ver));
1337         all_string_sub(filter, "%u", "*", sizeof(pstring));
1338
1339         machine_mask    = ((acb_mask != 0) && (acb_mask & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)));
1340         user_mask       = ((acb_mask != 0) && (acb_mask & ACB_NORMAL));
1341
1342         if (machine_mask) {
1343                 pstrcpy(suffix, lp_ldap_machine_suffix());
1344         } else if (user_mask) {
1345                 pstrcpy(suffix, lp_ldap_user_suffix());
1346         } else {
1347                 pstrcpy(suffix, lp_ldap_suffix());
1348         }
1349
1350         DEBUG(10,("ldapsam_setsampwent: LDAP Query for acb_mask 0x%x will use suffix %s\n", 
1351                 acb_mask, suffix));
1352
1353         attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
1354         rc = smbldap_search(ldap_state->smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter, 
1355                             attr_list, 0, &ldap_state->result);
1356         talloc_free( attr_list );
1357
1358         if (rc != LDAP_SUCCESS) {
1359                 DEBUG(0, ("ldapsam_setsampwent: LDAP search failed: %s\n", ldap_err2string(rc)));
1360                 DEBUG(3, ("ldapsam_setsampwent: Query was: %s, %s\n", suffix, filter));
1361                 ldap_msgfree(ldap_state->result);
1362                 ldap_state->result = NULL;
1363                 return NT_STATUS_UNSUCCESSFUL;
1364         }
1365
1366         DEBUG(2, ("ldapsam_setsampwent: %d entries in the base %s\n",
1367                 ldap_count_entries(ldap_state->smbldap_state->ldap_struct, 
1368                 ldap_state->result), suffix));
1369
1370         ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
1371                                  ldap_state->result);
1372         ldap_state->index = 0;
1373
1374         return NT_STATUS_OK;
1375 }
1376
1377 /**********************************************************************
1378  End enumeration of the LDAP password list.
1379 *********************************************************************/
1380
1381 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1382 {
1383         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1384         if (ldap_state->result) {
1385                 ldap_msgfree(ldap_state->result);
1386                 ldap_state->result = NULL;
1387         }
1388 }
1389
1390 /**********************************************************************
1391 Get the next entry in the LDAP password database.
1392 *********************************************************************/
1393
1394 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods,
1395                                     SAM_ACCOUNT *user)
1396 {
1397         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1398         struct ldapsam_privates *ldap_state =
1399                 (struct ldapsam_privates *)my_methods->private_data;
1400         BOOL bret = False;
1401
1402         while (!bret) {
1403                 if (!ldap_state->entry)
1404                         return ret;
1405                 
1406                 ldap_state->index++;
1407                 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
1408                 
1409                 ldap_state->entry = ldap_next_entry(priv2ld(ldap_state),
1410                                                     ldap_state->entry); 
1411         }
1412
1413         return NT_STATUS_OK;
1414 }
1415
1416 static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list,
1417                         const char *new_attr)
1418 {
1419         int i;
1420
1421         if (new_attr == NULL) {
1422                 return;
1423         }
1424
1425         for (i=0; (*attr_list)[i] != NULL; i++) {
1426                 ;
1427         }
1428
1429         (*attr_list) = TALLOC_REALLOC_ARRAY(mem_ctx, (*attr_list),
1430                                             const char *,  i+2);
1431         SMB_ASSERT((*attr_list) != NULL);
1432         (*attr_list)[i] = talloc_strdup((*attr_list), new_attr);
1433         (*attr_list)[i+1] = NULL;
1434 }
1435
1436 /**********************************************************************
1437 Get SAM_ACCOUNT entry from LDAP by username.
1438 *********************************************************************/
1439
1440 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
1441 {
1442         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1443         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1444         LDAPMessage *result = NULL;
1445         LDAPMessage *entry = NULL;
1446         int count;
1447         const char ** attr_list;
1448         int rc;
1449         
1450         attr_list = get_userattr_list( user->mem_ctx, ldap_state->schema_ver );
1451         append_attr(user->mem_ctx, &attr_list,
1452                     get_userattr_key2string(ldap_state->schema_ver,
1453                                             LDAP_ATTR_MOD_TIMESTAMP));
1454         append_attr(user->mem_ctx, &attr_list, "uidNumber");
1455         rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result,
1456                                            attr_list);
1457         talloc_free( attr_list );
1458
1459         if ( rc != LDAP_SUCCESS ) 
1460                 return NT_STATUS_NO_SUCH_USER;
1461         
1462         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1463         
1464         if (count < 1) {
1465                 DEBUG(4, ("ldapsam_getsampwnam: Unable to locate user [%s] count=%d\n", sname, count));
1466                 ldap_msgfree(result);
1467                 return NT_STATUS_NO_SUCH_USER;
1468         } else if (count > 1) {
1469                 DEBUG(1, ("ldapsam_getsampwnam: Duplicate entries for this user [%s] Failing. count=%d\n", sname, count));
1470                 ldap_msgfree(result);
1471                 return NT_STATUS_NO_SUCH_USER;
1472         }
1473
1474         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1475         if (entry) {
1476                 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1477                         DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1478                         ldap_msgfree(result);
1479                         return NT_STATUS_NO_SUCH_USER;
1480                 }
1481                 pdb_set_backend_private_data(user, result, NULL,
1482                                              my_methods, PDB_CHANGED);
1483                 talloc_autofree_ldapmsg(user->mem_ctx, result);
1484                 ret = NT_STATUS_OK;
1485         } else {
1486                 ldap_msgfree(result);
1487         }
1488         return ret;
1489 }
1490
1491 static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, 
1492                                    const DOM_SID *sid, LDAPMessage **result) 
1493 {
1494         int rc = -1;
1495         const char ** attr_list;
1496         uint32 rid;
1497
1498         switch ( ldap_state->schema_ver ) {
1499                 case SCHEMAVER_SAMBASAMACCOUNT: {
1500                         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1501                         if (tmp_ctx == NULL) {
1502                                 return LDAP_NO_MEMORY;
1503                         }
1504
1505                         attr_list = get_userattr_list(tmp_ctx,
1506                                                       ldap_state->schema_ver);
1507                         append_attr(tmp_ctx, &attr_list,
1508                                     get_userattr_key2string(
1509                                             ldap_state->schema_ver,
1510                                             LDAP_ATTR_MOD_TIMESTAMP));
1511                         append_attr(tmp_ctx, &attr_list, "uidNumber");
1512                         rc = ldapsam_search_suffix_by_sid(ldap_state, sid,
1513                                                           result, attr_list);
1514                         talloc_free(tmp_ctx);
1515
1516                         if ( rc != LDAP_SUCCESS ) 
1517                                 return rc;
1518                         break;
1519                 }
1520                         
1521                 case SCHEMAVER_SAMBAACCOUNT:
1522                         if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) {
1523                                 return rc;
1524                         }
1525                 
1526                         attr_list = get_userattr_list(NULL,
1527                                                       ldap_state->schema_ver);
1528                         rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list );
1529                         talloc_free( attr_list );
1530
1531                         if ( rc != LDAP_SUCCESS ) 
1532                                 return rc;
1533                         break;
1534         }
1535         return rc;
1536 }
1537
1538 /**********************************************************************
1539  Get SAM_ACCOUNT entry from LDAP by SID.
1540 *********************************************************************/
1541
1542 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1543 {
1544         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1545         LDAPMessage *result = NULL;
1546         LDAPMessage *entry = NULL;
1547         int count;
1548         int rc;
1549         fstring sid_string;
1550
1551         rc = ldapsam_get_ldap_user_by_sid(ldap_state, 
1552                                           sid, &result); 
1553         if (rc != LDAP_SUCCESS)
1554                 return NT_STATUS_NO_SUCH_USER;
1555
1556         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1557         
1558         if (count < 1) {
1559                 DEBUG(4, ("ldapsam_getsampwsid: Unable to locate SID [%s] count=%d\n", sid_to_string(sid_string, sid),
1560                        count));
1561                 ldap_msgfree(result);
1562                 return NT_STATUS_NO_SUCH_USER;
1563         }  else if (count > 1) {
1564                 DEBUG(1, ("ldapsam_getsampwsid: More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid),
1565                        count));
1566                 ldap_msgfree(result);
1567                 return NT_STATUS_NO_SUCH_USER;
1568         }
1569
1570         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1571         if (!entry) {
1572                 ldap_msgfree(result);
1573                 return NT_STATUS_NO_SUCH_USER;
1574         }
1575
1576         if (!init_sam_from_ldap(ldap_state, user, entry)) {
1577                 DEBUG(1,("ldapsam_getsampwsid: init_sam_from_ldap failed!\n"));
1578                 ldap_msgfree(result);
1579                 return NT_STATUS_NO_SUCH_USER;
1580         }
1581
1582         pdb_set_backend_private_data(user, result, NULL,
1583                                      my_methods, PDB_CHANGED);
1584         talloc_autofree_ldapmsg(user->mem_ctx, result);
1585         return NT_STATUS_OK;
1586 }       
1587
1588 static BOOL ldapsam_can_pwchange_exop(struct smbldap_state *ldap_state)
1589 {
1590         return smbldap_has_extension(ldap_state, LDAP_EXOP_MODIFY_PASSWD);
1591 }
1592
1593 /********************************************************************
1594  Do the actual modification - also change a plaintext passord if 
1595  it it set.
1596 **********************************************************************/
1597
1598 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, 
1599                                      SAM_ACCOUNT *newpwd, char *dn,
1600                                      LDAPMod **mods, int ldap_op, 
1601                                      BOOL (*need_update)(const SAM_ACCOUNT *, enum pdb_elements))
1602 {
1603         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1604         int rc;
1605         
1606         if (!my_methods || !newpwd || !dn) {
1607                 return NT_STATUS_INVALID_PARAMETER;
1608         }
1609         
1610         if (!mods) {
1611                 DEBUG(5,("ldapsam_modify_entry: mods is empty: nothing to modify\n"));
1612                 /* may be password change below however */
1613         } else {
1614                 switch(ldap_op) {
1615                         case LDAP_MOD_ADD: 
1616                                 smbldap_set_mod(&mods, LDAP_MOD_ADD, 
1617                                                 "objectclass", 
1618                                                 LDAP_OBJ_ACCOUNT);
1619                                 rc = smbldap_add(ldap_state->smbldap_state, 
1620                                                  dn, mods);
1621                                 break;
1622                         case LDAP_MOD_REPLACE: 
1623                                 rc = smbldap_modify(ldap_state->smbldap_state, 
1624                                                     dn ,mods);
1625                                 break;
1626                         default:        
1627                                 DEBUG(0,("ldapsam_modify_entry: Wrong LDAP operation type: %d!\n", 
1628                                          ldap_op));
1629                                 return NT_STATUS_INVALID_PARAMETER;
1630                 }
1631                 
1632                 if (rc!=LDAP_SUCCESS) {
1633                         return NT_STATUS_UNSUCCESSFUL;
1634                 }  
1635         }
1636         
1637         if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
1638                         (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
1639                         need_update(newpwd, PDB_PLAINTEXT_PW) &&
1640                         (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1641                 BerElement *ber;
1642                 struct berval *bv;
1643                 char *retoid = NULL;
1644                 struct berval *retdata = NULL;
1645                 char *utf8_password;
1646                 char *utf8_dn;
1647
1648                 if (!ldap_state->is_nds_ldap) {
1649                         if (!ldapsam_can_pwchange_exop(ldap_state->smbldap_state)) {
1650                                 DEBUG(2, ("ldap password change requested, but LDAP "
1651                                           "server does not support it -- ignoring\n"));
1652                                 return NT_STATUS_OK;
1653                         }
1654                 }
1655
1656                 if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
1657                         return NT_STATUS_NO_MEMORY;
1658                 }
1659
1660                 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
1661                         return NT_STATUS_NO_MEMORY;
1662                 }
1663
1664                 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1665                         DEBUG(0,("ber_alloc_t returns NULL\n"));
1666                         SAFE_FREE(utf8_password);
1667                         return NT_STATUS_UNSUCCESSFUL;
1668                 }
1669
1670                 ber_printf (ber, "{");
1671                 ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, utf8_dn);
1672                 ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, utf8_password);
1673                 ber_printf (ber, "N}");
1674
1675                 if ((rc = ber_flatten (ber, &bv))<0) {
1676                         DEBUG(0,("ldapsam_modify_entry: ber_flatten returns a value <0\n"));
1677                         ber_free(ber,1);
1678                         SAFE_FREE(utf8_dn);
1679                         SAFE_FREE(utf8_password);
1680                         return NT_STATUS_UNSUCCESSFUL;
1681                 }
1682                 
1683                 SAFE_FREE(utf8_dn);
1684                 SAFE_FREE(utf8_password);
1685                 ber_free(ber, 1);
1686
1687                 if (!ldap_state->is_nds_ldap) {
1688                         rc = smbldap_extended_operation(ldap_state->smbldap_state, 
1689                                                         LDAP_EXOP_MODIFY_PASSWD,
1690                                                         bv, NULL, NULL, &retoid, 
1691                                                         &retdata);
1692                 } else {
1693                         rc = pdb_nds_set_password(ldap_state->smbldap_state, dn,
1694                                                         pdb_get_plaintext_passwd(newpwd));
1695                 }
1696                 if (rc != LDAP_SUCCESS) {
1697                         char *ld_error = NULL;
1698
1699                         if (rc == LDAP_OBJECT_CLASS_VIOLATION) {
1700                                 DEBUG(3, ("Could not set userPassword "
1701                                           "attribute due to an objectClass "
1702                                           "violation -- ignoring\n"));
1703                                 ber_bvfree(bv);
1704                                 return NT_STATUS_OK;
1705                         }
1706
1707                         ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1708                                         &ld_error);
1709                         DEBUG(0,("ldapsam_modify_entry: LDAP Password could not be changed for user %s: %s\n\t%s\n",
1710                                 pdb_get_username(newpwd), ldap_err2string(rc), ld_error?ld_error:"unknown"));
1711                         SAFE_FREE(ld_error);
1712                         ber_bvfree(bv);
1713                         return NT_STATUS_UNSUCCESSFUL;
1714                 } else {
1715                         DEBUG(3,("ldapsam_modify_entry: LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1716 #ifdef DEBUG_PASSWORD
1717                         DEBUG(100,("ldapsam_modify_entry: LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
1718 #endif    
1719                         if (retdata)
1720                                 ber_bvfree(retdata);
1721                         if (retoid)
1722                                 ldap_memfree(retoid);
1723                 }
1724                 ber_bvfree(bv);
1725         }
1726         return NT_STATUS_OK;
1727 }
1728
1729 /**********************************************************************
1730  Delete entry from LDAP for username.
1731 *********************************************************************/
1732
1733 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods,
1734                                            SAM_ACCOUNT * sam_acct)
1735 {
1736         struct ldapsam_privates *priv =
1737                 (struct ldapsam_privates *)my_methods->private_data;
1738         const char *sname;
1739         int rc;
1740         LDAPMessage *msg, *entry;
1741         NTSTATUS result = NT_STATUS_NO_MEMORY;
1742         const char **attr_list;
1743         TALLOC_CTX *mem_ctx;
1744
1745         if (!sam_acct) {
1746                 DEBUG(0, ("ldapsam_delete_sam_account: sam_acct was NULL!\n"));
1747                 return NT_STATUS_INVALID_PARAMETER;
1748         }
1749
1750         sname = pdb_get_username(sam_acct);
1751
1752         DEBUG(3, ("ldapsam_delete_sam_account: Deleting user %s from "
1753                   "LDAP.\n", sname));
1754
1755         mem_ctx = talloc_new(NULL);
1756         if (mem_ctx == NULL) {
1757                 DEBUG(0, ("talloc_new failed\n"));
1758                 goto done;
1759         }
1760
1761         attr_list = get_userattr_delete_list(mem_ctx, priv->schema_ver );
1762         if (attr_list == NULL) {
1763                 goto done;
1764         }
1765
1766         rc = ldapsam_search_suffix_by_name(priv, sname, &msg, attr_list);
1767
1768         if ((rc != LDAP_SUCCESS) ||
1769             (ldap_count_entries(priv2ld(priv), msg) != 1) ||
1770             ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
1771                 DEBUG(5, ("Could not find user %s\n", sname));
1772                 result = NT_STATUS_NO_SUCH_USER;
1773                 goto done;
1774         }
1775         
1776         rc = ldapsam_delete_entry(
1777                 priv, mem_ctx, entry,
1778                 priv->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ?
1779                 LDAP_OBJ_SAMBASAMACCOUNT : LDAP_OBJ_SAMBAACCOUNT,
1780                 attr_list);
1781
1782         result = (rc == LDAP_SUCCESS) ?
1783                 NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
1784
1785  done:
1786         talloc_free(mem_ctx);
1787         return result;
1788 }
1789
1790 /**********************************************************************
1791  Helper function to determine for update_sam_account whether
1792  we need LDAP modification.
1793 *********************************************************************/
1794
1795 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
1796                                enum pdb_elements element)
1797 {
1798         return IS_SAM_CHANGED(sampass, element);
1799 }
1800
1801 /**********************************************************************
1802  Update SAM_ACCOUNT.
1803 *********************************************************************/
1804
1805 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1806 {
1807         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1808         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1809         int rc = 0;
1810         char *dn;
1811         LDAPMessage *result = NULL;
1812         LDAPMessage *entry = NULL;
1813         LDAPMod **mods = NULL;
1814         const char **attr_list;
1815
1816         result = pdb_get_backend_private_data(newpwd, my_methods);
1817         if (!result) {
1818                 attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
1819                 rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list );
1820                 talloc_free( attr_list );
1821                 if (rc != LDAP_SUCCESS) {
1822                         return NT_STATUS_UNSUCCESSFUL;
1823                 }
1824                 pdb_set_backend_private_data(newpwd, result, NULL,
1825                                              my_methods, PDB_CHANGED);
1826                 talloc_autofree_ldapmsg(newpwd->mem_ctx, result);
1827         }
1828
1829         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
1830                 DEBUG(0, ("ldapsam_update_sam_account: No user to modify!\n"));
1831                 return NT_STATUS_UNSUCCESSFUL;
1832         }
1833
1834         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1835         dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
1836         if (!dn) {
1837                 return NT_STATUS_UNSUCCESSFUL;
1838         }
1839
1840         DEBUG(4, ("ldapsam_update_sam_account: user %s to be modified has dn: %s\n", pdb_get_username(newpwd), dn));
1841
1842         if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1843                                 element_is_changed)) {
1844                 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1845                 SAFE_FREE(dn);
1846                 if (mods != NULL)
1847                         ldap_mods_free(mods,True);
1848                 return NT_STATUS_UNSUCCESSFUL;
1849         }
1850         
1851         if (mods == NULL) {
1852                 DEBUG(4,("ldapsam_update_sam_account: mods is empty: nothing to update for user: %s\n",
1853                          pdb_get_username(newpwd)));
1854                 SAFE_FREE(dn);
1855                 return NT_STATUS_OK;
1856         }
1857         
1858         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
1859         ldap_mods_free(mods,True);
1860         SAFE_FREE(dn);
1861
1862         if (!NT_STATUS_IS_OK(ret)) {
1863                 return ret;
1864         }
1865
1866         DEBUG(2, ("ldapsam_update_sam_account: successfully modified uid = %s in the LDAP database\n",
1867                   pdb_get_username(newpwd)));
1868         return NT_STATUS_OK;
1869 }
1870
1871 /***************************************************************************
1872  Renames a SAM_ACCOUNT
1873  - The "rename user script" has full responsibility for changing everything
1874 ***************************************************************************/
1875
1876 static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
1877                                            SAM_ACCOUNT *old_acct, 
1878                                            const char *newname)
1879 {
1880         const char *oldname;
1881         int rc;
1882         pstring rename_script;
1883
1884         if (!old_acct) {
1885                 DEBUG(0, ("ldapsam_rename_sam_account: old_acct was NULL!\n"));
1886                 return NT_STATUS_INVALID_PARAMETER;
1887         }
1888         if (!newname) {
1889                 DEBUG(0, ("ldapsam_rename_sam_account: newname was NULL!\n"));
1890                 return NT_STATUS_INVALID_PARAMETER;
1891         }
1892                 
1893         oldname = pdb_get_username(old_acct);
1894
1895         /* rename the posix user */
1896         pstrcpy(rename_script, lp_renameuser_script());
1897
1898         if (!(*rename_script))
1899                 return NT_STATUS_ACCESS_DENIED;
1900
1901         DEBUG (3, ("ldapsam_rename_sam_account: Renaming user %s to %s.\n", 
1902                    oldname, newname));
1903
1904         pstring_sub(rename_script, "%unew", newname);
1905         pstring_sub(rename_script, "%uold", oldname);
1906         rc = smbrun(rename_script, NULL);
1907
1908         DEBUG(rc ? 0 : 3,("Running the command `%s' gave %d\n", 
1909                           rename_script, rc));
1910
1911         if (rc)
1912                 return NT_STATUS_UNSUCCESSFUL;
1913
1914         return NT_STATUS_OK;
1915 }
1916
1917 /**********************************************************************
1918  Helper function to determine for update_sam_account whether
1919  we need LDAP modification.
1920  *********************************************************************/
1921
1922 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
1923                                       enum pdb_elements element)
1924 {
1925         return (IS_SAM_SET(sampass, element) ||
1926                 IS_SAM_CHANGED(sampass, element));
1927 }
1928
1929 /**********************************************************************
1930  Add SAM_ACCOUNT to LDAP.
1931 *********************************************************************/
1932
1933 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1934 {
1935         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1936         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1937         int rc;
1938         LDAPMessage     *result = NULL;
1939         LDAPMessage     *entry  = NULL;
1940         pstring         dn;
1941         LDAPMod         **mods = NULL;
1942         int             ldap_op = LDAP_MOD_REPLACE;
1943         uint32          num_result;
1944         const char      **attr_list;
1945         char            *escape_user;
1946         const char      *username = pdb_get_username(newpwd);
1947         const DOM_SID   *sid = pdb_get_user_sid(newpwd);
1948         pstring         filter;
1949         fstring         sid_string;
1950
1951         if (!username || !*username) {
1952                 DEBUG(0, ("ldapsam_add_sam_account: Cannot add user without a username!\n"));
1953                 return NT_STATUS_INVALID_PARAMETER;
1954         }
1955
1956         /* free this list after the second search or in case we exit on failure */
1957         attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
1958
1959         rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
1960
1961         if (rc != LDAP_SUCCESS) {
1962                 talloc_free( attr_list );
1963                 return NT_STATUS_UNSUCCESSFUL;
1964         }
1965
1966         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
1967                 DEBUG(0,("ldapsam_add_sam_account: User '%s' already in the base, with samba attributes\n", 
1968                          username));
1969                 ldap_msgfree(result);
1970                 talloc_free( attr_list );
1971                 return NT_STATUS_UNSUCCESSFUL;
1972         }
1973         ldap_msgfree(result);
1974         result = NULL;
1975
1976         if (element_is_set_or_changed(newpwd, PDB_USERSID)) {
1977                 rc = ldapsam_get_ldap_user_by_sid(ldap_state, 
1978                                                   sid, &result); 
1979                 if (rc == LDAP_SUCCESS) {
1980                         if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
1981                                 DEBUG(0,("ldapsam_add_sam_account: SID '%s' already in the base, with samba attributes\n", 
1982                                          sid_to_string(sid_string, sid)));
1983                                 talloc_free( attr_list );
1984                                 ldap_msgfree(result);
1985                                 return NT_STATUS_UNSUCCESSFUL;
1986                         }
1987                         ldap_msgfree(result);
1988                 }
1989         }
1990
1991         /* does the entry already exist but without a samba attributes?
1992            we need to return the samba attributes here */
1993            
1994         escape_user = escape_ldap_string_alloc( username );
1995         pstrcpy( filter, "(uid=%u)" );
1996         all_string_sub( filter, "%u", escape_user, sizeof(filter) );
1997         SAFE_FREE( escape_user );
1998
1999         rc = smbldap_search_suffix(ldap_state->smbldap_state, 
2000                                    filter, attr_list, &result);
2001         if ( rc != LDAP_SUCCESS ) {
2002                 talloc_free( attr_list );
2003                 return NT_STATUS_UNSUCCESSFUL;
2004         }
2005
2006         num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
2007         
2008         if (num_result > 1) {
2009                 DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
2010                 talloc_free( attr_list );
2011                 ldap_msgfree(result);
2012                 return NT_STATUS_UNSUCCESSFUL;
2013         }
2014         
2015         /* Check if we need to update an existing entry */
2016         if (num_result == 1) {
2017                 char *tmp;
2018                 
2019                 DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
2020                 ldap_op = LDAP_MOD_REPLACE;
2021                 entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
2022                 tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
2023                 if (!tmp) {
2024                         talloc_free( attr_list );
2025                         ldap_msgfree(result);
2026                         return NT_STATUS_UNSUCCESSFUL;
2027                 }
2028                 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2029                 SAFE_FREE(tmp);
2030
2031         } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) {
2032
2033                 /* There might be a SID for this account already - say an idmap entry */
2034
2035                 pstr_sprintf(filter, "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))", 
2036                          get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
2037                          sid_to_string(sid_string, sid),
2038                          LDAP_OBJ_IDMAP_ENTRY,
2039                          LDAP_OBJ_SID_ENTRY);
2040                 
2041                 /* free old result before doing a new search */
2042                 if (result != NULL) {
2043                         ldap_msgfree(result);
2044                         result = NULL;
2045                 }
2046                 rc = smbldap_search_suffix(ldap_state->smbldap_state, 
2047                                            filter, attr_list, &result);
2048                         
2049                 if ( rc != LDAP_SUCCESS ) {
2050                         talloc_free( attr_list );
2051                         return NT_STATUS_UNSUCCESSFUL;
2052                 }
2053                 
2054                 num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
2055                 
2056                 if (num_result > 1) {
2057                         DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
2058                         talloc_free( attr_list );
2059                         ldap_msgfree(result);
2060                         return NT_STATUS_UNSUCCESSFUL;
2061                 }
2062                 
2063                 /* Check if we need to update an existing entry */
2064                 if (num_result == 1) {
2065                         char *tmp;
2066                         
2067                         DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
2068                         ldap_op = LDAP_MOD_REPLACE;
2069                         entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
2070                         tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
2071                         if (!tmp) {
2072                                 talloc_free( attr_list );
2073                                 ldap_msgfree(result);
2074                                 return NT_STATUS_UNSUCCESSFUL;
2075                         }
2076                         slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2077                         SAFE_FREE(tmp);
2078                 }
2079         }
2080         
2081         talloc_free( attr_list );
2082
2083         if (num_result == 0) {
2084                 /* Check if we need to add an entry */
2085                 DEBUG(3,("ldapsam_add_sam_account: Adding new user\n"));
2086                 ldap_op = LDAP_MOD_ADD;
2087                 if (username[strlen(username)-1] == '$') {
2088                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2089                 } else {
2090                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
2091                 }
2092         }
2093
2094         if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2095                                 element_is_set_or_changed)) {
2096                 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2097                 ldap_msgfree(result);
2098                 if (mods != NULL)
2099                         ldap_mods_free(mods,True);
2100                 return NT_STATUS_UNSUCCESSFUL;          
2101         }
2102         
2103         ldap_msgfree(result);
2104
2105         if (mods == NULL) {
2106                 DEBUG(0,("ldapsam_add_sam_account: mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2107                 return NT_STATUS_UNSUCCESSFUL;
2108         }
2109         switch ( ldap_state->schema_ver ) {
2110                 case SCHEMAVER_SAMBAACCOUNT:
2111                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT);
2112                         break;
2113                 case SCHEMAVER_SAMBASAMACCOUNT:
2114                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT);
2115                         break;
2116                 default:
2117                         DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
2118                         break;
2119         }
2120
2121         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
2122         if (!NT_STATUS_IS_OK(ret)) {
2123                 DEBUG(0,("ldapsam_add_sam_account: failed to modify/add user with uid = %s (dn = %s)\n",
2124                          pdb_get_username(newpwd),dn));
2125                 ldap_mods_free(mods, True);
2126                 return ret;
2127         }
2128
2129         DEBUG(2,("ldapsam_add_sam_account: added: uid == %s in the LDAP database\n", pdb_get_username(newpwd)));
2130         ldap_mods_free(mods, True);
2131         
2132         return NT_STATUS_OK;
2133 }
2134
2135 /**********************************************************************
2136  *********************************************************************/
2137
2138 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2139                                      const char *filter,
2140                                      LDAPMessage ** result)
2141 {
2142         int scope = LDAP_SCOPE_SUBTREE;
2143         int rc;
2144         const char **attr_list;
2145
2146         attr_list = get_attr_list(NULL, groupmap_attr_list);
2147         rc = smbldap_search(ldap_state->smbldap_state, 
2148                             lp_ldap_group_suffix (), scope,
2149                             filter, attr_list, 0, result);
2150         talloc_free(attr_list);
2151
2152         return rc;
2153 }
2154
2155 /**********************************************************************
2156  *********************************************************************/
2157
2158 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
2159                                  GROUP_MAP *map, LDAPMessage *entry)
2160 {
2161         pstring temp;
2162
2163         if (ldap_state == NULL || map == NULL || entry == NULL ||
2164                         ldap_state->smbldap_state->ldap_struct == NULL) {
2165                 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2166                 return False;
2167         }
2168
2169         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
2170                         get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp)) {
2171                 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n", 
2172                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GIDNUMBER)));
2173                 return False;
2174         }
2175         DEBUG(2, ("init_group_from_ldap: Entry found for group: %s\n", temp));
2176
2177         map->gid = (gid_t)atol(temp);
2178
2179         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
2180                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp)) {
2181                 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n",
2182                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID)));
2183                 return False;
2184         }
2185         
2186         if (!string_to_sid(&map->sid, temp)) {
2187                 DEBUG(1, ("SID string [%s] could not be read as a valid SID\n", temp));
2188                 return False;
2189         }
2190
2191         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
2192                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp)) {
2193                 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n",
2194                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
2195                 return False;
2196         }
2197         map->sid_name_use = (enum SID_NAME_USE)atol(temp);
2198
2199         if ((map->sid_name_use < SID_NAME_USER) ||
2200                         (map->sid_name_use > SID_NAME_UNKNOWN)) {
2201                 DEBUG(0, ("init_group_from_ldap: Unknown Group type: %d\n", map->sid_name_use));
2202                 return False;
2203         }
2204
2205         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
2206                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp)) {
2207                 temp[0] = '\0';
2208                 if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
2209                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp)) 
2210                 {
2211                         DEBUG(0, ("init_group_from_ldap: Attributes cn not found either \
2212 for gidNumber(%lu)\n",(unsigned long)map->gid));
2213                         return False;
2214                 }
2215         }
2216         fstrcpy(map->nt_name, temp);
2217
2218         if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
2219                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp)) {
2220                 temp[0] = '\0';
2221         }
2222         fstrcpy(map->comment, temp);
2223
2224         if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
2225                 store_gid_sid_cache(&map->sid, map->gid);
2226         }
2227
2228         return True;
2229 }
2230
2231 /**********************************************************************
2232  *********************************************************************/
2233
2234 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2235                                  const char *filter,
2236                                  GROUP_MAP *map)
2237 {
2238         struct ldapsam_privates *ldap_state =
2239                 (struct ldapsam_privates *)methods->private_data;
2240         LDAPMessage *result = NULL;
2241         LDAPMessage *entry = NULL;
2242         int count;
2243
2244         if (ldapsam_search_one_group(ldap_state, filter, &result)
2245             != LDAP_SUCCESS) {
2246                 return NT_STATUS_NO_SUCH_GROUP;
2247         }
2248
2249         count = ldap_count_entries(priv2ld(ldap_state), result);
2250
2251         if (count < 1) {
2252                 DEBUG(4, ("ldapsam_getgroup: Did not find group\n"));
2253                 ldap_msgfree(result);
2254                 return NT_STATUS_NO_SUCH_GROUP;
2255         }
2256
2257         if (count > 1) {
2258                 DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: "
2259                           "count=%d\n", filter, count));
2260                 ldap_msgfree(result);
2261                 return NT_STATUS_NO_SUCH_GROUP;
2262         }
2263
2264         entry = ldap_first_entry(priv2ld(ldap_state), result);
2265
2266         if (!entry) {
2267                 ldap_msgfree(result);
2268                 return NT_STATUS_UNSUCCESSFUL;
2269         }
2270
2271         if (!init_group_from_ldap(ldap_state, map, entry)) {
2272                 DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for "
2273                           "group filter %s\n", filter));
2274                 ldap_msgfree(result);
2275                 return NT_STATUS_NO_SUCH_GROUP;
2276         }
2277
2278         ldap_msgfree(result);
2279         return NT_STATUS_OK;
2280 }
2281
2282 /**********************************************************************
2283  *********************************************************************/
2284
2285 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2286                                  DOM_SID sid)
2287 {
2288         pstring filter;
2289
2290         pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
2291                 LDAP_OBJ_GROUPMAP, 
2292                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID),
2293                 sid_string_static(&sid));
2294
2295         return ldapsam_getgroup(methods, filter, map);
2296 }
2297
2298 /**********************************************************************
2299  *********************************************************************/
2300
2301 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2302                                  gid_t gid)
2303 {
2304         pstring filter;
2305
2306         pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
2307                 LDAP_OBJ_GROUPMAP,
2308                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
2309                 (unsigned long)gid);
2310
2311         return ldapsam_getgroup(methods, filter, map);
2312 }
2313
2314 /**********************************************************************
2315  *********************************************************************/
2316
2317 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2318                                  const char *name)
2319 {
2320         pstring filter;
2321         char *escape_name = escape_ldap_string_alloc(name);
2322
2323         if (!escape_name) {
2324                 return NT_STATUS_NO_MEMORY;
2325         }
2326
2327         pstr_sprintf(filter, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
2328                 LDAP_OBJ_GROUPMAP,
2329                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name,
2330                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), escape_name);
2331
2332         SAFE_FREE(escape_name);
2333
2334         return ldapsam_getgroup(methods, filter, map);
2335 }
2336
2337 static void add_rid_to_array_unique(TALLOC_CTX *mem_ctx,
2338                                     uint32 rid, uint32 **pp_rids, size_t *p_num)
2339 {
2340         size_t i;
2341
2342         for (i=0; i<*p_num; i++) {
2343                 if ((*pp_rids)[i] == rid)
2344                         return;
2345         }
2346         
2347         *pp_rids = TALLOC_REALLOC_ARRAY(mem_ctx, *pp_rids, uint32, *p_num+1);
2348
2349         if (*pp_rids == NULL)
2350                 return;
2351
2352         (*pp_rids)[*p_num] = rid;
2353         *p_num += 1;
2354 }
2355
2356 static BOOL ldapsam_extract_rid_from_entry(LDAP *ldap_struct,
2357                                            LDAPMessage *entry,
2358                                            const DOM_SID *domain_sid,
2359                                            uint32 *rid)
2360 {
2361         fstring str;
2362         DOM_SID sid;
2363
2364         if (!smbldap_get_single_attribute(ldap_struct, entry, "sambaSID",
2365                                           str, sizeof(str)-1)) {
2366                 DEBUG(10, ("Could not find sambaSID attribute\n"));
2367                 return False;
2368         }
2369
2370         if (!string_to_sid(&sid, str)) {
2371                 DEBUG(10, ("Could not convert string %s to sid\n", str));
2372                 return False;
2373         }
2374
2375         if (sid_compare_domain(&sid, domain_sid) != 0) {
2376                 DEBUG(10, ("SID %s is not in expected domain %s\n",
2377                            str, sid_string_static(domain_sid)));
2378                 return False;
2379         }
2380
2381         if (!sid_peek_rid(&sid, rid)) {
2382                 DEBUG(10, ("Could not peek into RID\n"));
2383                 return False;
2384         }
2385
2386         return True;
2387 }
2388
2389 static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
2390                                            TALLOC_CTX *mem_ctx,
2391                                            const DOM_SID *group,
2392                                            uint32 **pp_member_rids,
2393                                            size_t *p_num_members)
2394 {
2395         struct ldapsam_privates *ldap_state =
2396                 (struct ldapsam_privates *)methods->private_data;
2397         struct smbldap_state *conn = ldap_state->smbldap_state;
2398         pstring filter;
2399         int rc, count;
2400         LDAPMessage *msg = NULL;
2401         LDAPMessage *entry;
2402         char **values = NULL;
2403         char **memberuid;
2404         char *sid_filter = NULL;
2405         char *tmp;
2406         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2407
2408         *pp_member_rids = NULL;
2409         *p_num_members = 0;
2410
2411         pstr_sprintf(filter,
2412                      "(&(objectClass=sambaSamAccount)"
2413                      "(sambaPrimaryGroupSid=%s))",
2414                      sid_string_static(group));
2415
2416         {
2417                 const char *attrs[] = { "sambaSID", NULL };
2418                 rc = smbldap_search(conn, lp_ldap_user_suffix(),
2419                                     LDAP_SCOPE_SUBTREE, filter, attrs, 0,
2420                                     &msg);
2421         }
2422
2423         if (rc != LDAP_SUCCESS)
2424                 goto done;
2425
2426         for (entry = ldap_first_entry(conn->ldap_struct, msg);
2427              entry != NULL;
2428              entry = ldap_next_entry(conn->ldap_struct, entry))
2429         {
2430                 uint32 rid;
2431
2432                 if (!ldapsam_extract_rid_from_entry(conn->ldap_struct,
2433                                                     entry,
2434                                                     get_global_sam_sid(),
2435                                                     &rid)) {
2436                         DEBUG(2, ("Could not find sid from ldap entry\n"));
2437                         continue;
2438                 }
2439
2440                 add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
2441                                         p_num_members);
2442         }
2443
2444         if (msg != NULL)
2445                 ldap_msgfree(msg);
2446
2447         pstr_sprintf(filter,
2448                      "(&(objectClass=sambaGroupMapping)"
2449                      "(objectClass=posixGroup)"
2450                      "(sambaSID=%s))",
2451                      sid_string_static(group));
2452
2453         {
2454                 const char *attrs[] = { "memberUid", NULL };
2455                 rc = smbldap_search(conn, lp_ldap_user_suffix(),
2456                                     LDAP_SCOPE_SUBTREE, filter, attrs, 0,
2457                                     &msg);
2458         }
2459
2460         if (rc != LDAP_SUCCESS)
2461                 goto done;
2462
2463         count = ldap_count_entries(conn->ldap_struct, msg);
2464
2465         if (count > 1) {
2466                 DEBUG(1, ("Found more than one groupmap entry for %s\n",
2467                           sid_string_static(group)));
2468                 goto done;
2469         }
2470
2471         if (count == 0) {
2472                 result = NT_STATUS_OK;
2473                 goto done;
2474         }
2475
2476         entry = ldap_first_entry(conn->ldap_struct, msg);
2477         if (entry == NULL)
2478                 goto done;
2479
2480         values = ldap_get_values(conn->ldap_struct, msg, "memberUid");
2481         if (values == NULL) {
2482                 result = NT_STATUS_OK;
2483                 goto done;
2484         }
2485
2486         sid_filter = SMB_STRDUP("(&(objectClass=sambaSamAccount)(|");
2487         if (sid_filter == NULL) {
2488                 result = NT_STATUS_NO_MEMORY;
2489                 goto done;
2490         }
2491
2492         for (memberuid = values; *memberuid != NULL; memberuid += 1) {
2493                 tmp = sid_filter;
2494                 asprintf(&sid_filter, "%s(uid=%s)", tmp, *memberuid);
2495                 free(tmp);
2496                 if (sid_filter == NULL) {
2497                         result = NT_STATUS_NO_MEMORY;
2498                         goto done;
2499                 }
2500         }
2501
2502         tmp = sid_filter;
2503         asprintf(&sid_filter, "%s))", sid_filter);
2504         free(tmp);
2505         if (sid_filter == NULL) {
2506                 result = NT_STATUS_NO_MEMORY;
2507                 goto done;
2508         }
2509
2510         {
2511                 const char *attrs[] = { "sambaSID", NULL };
2512                 rc = smbldap_search(conn, lp_ldap_user_suffix(),
2513                                     LDAP_SCOPE_SUBTREE, sid_filter, attrs, 0,
2514                                     &msg);
2515         }
2516
2517         if (rc != LDAP_SUCCESS)
2518                 goto done;
2519
2520         for (entry = ldap_first_entry(conn->ldap_struct, msg);
2521              entry != NULL;
2522              entry = ldap_next_entry(conn->ldap_struct, entry))
2523         {
2524                 fstring str;
2525                 DOM_SID sid;
2526                 uint32 rid;
2527
2528                 if (!smbldap_get_single_attribute(conn->ldap_struct,
2529                                                   entry, "sambaSID",
2530                                                   str, sizeof(str)-1))
2531                         continue;
2532
2533                 if (!string_to_sid(&sid, str))
2534                         goto done;
2535
2536                 if (!sid_check_is_in_our_domain(&sid)) {
2537                         DEBUG(1, ("Inconsistent SAM -- group member uid not "
2538                                   "in our domain\n"));
2539                         continue;
2540                 }
2541
2542                 sid_peek_rid(&sid, &rid);
2543
2544                 add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
2545                                         p_num_members);
2546         }
2547
2548         result = NT_STATUS_OK;
2549         
2550  done:
2551         SAFE_FREE(sid_filter);
2552
2553         if (values != NULL)
2554                 ldap_value_free(values);
2555
2556         if (msg != NULL)
2557                 ldap_msgfree(msg);
2558
2559         return result;
2560 }
2561
2562 static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
2563                                                TALLOC_CTX *mem_ctx,
2564                                                SAM_ACCOUNT *user,
2565                                                DOM_SID **pp_sids,
2566                                                gid_t **pp_gids,
2567                                                size_t *p_num_groups)
2568 {
2569         struct ldapsam_privates *ldap_state =
2570                 (struct ldapsam_privates *)methods->private_data;
2571         struct smbldap_state *conn = ldap_state->smbldap_state;
2572         pstring filter;
2573         const char *attrs[] = { "gidNumber", "sambaSID", NULL };
2574         char *escape_name;
2575         int rc;
2576         LDAPMessage *msg = NULL;
2577         LDAPMessage *entry;
2578         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2579         size_t num_sids, num_gids;
2580         gid_t primary_gid;
2581
2582         *pp_sids = NULL;
2583         num_sids = 0;
2584
2585         if (!sid_to_gid(pdb_get_group_sid(user), &primary_gid)) {
2586                 DEBUG(1, ("sid_to_gid failed for user's primary group\n"));
2587                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2588         }
2589
2590         escape_name = escape_ldap_string_alloc(pdb_get_username(user));
2591
2592         if (escape_name == NULL)
2593                 return NT_STATUS_NO_MEMORY;
2594
2595         pstr_sprintf(filter, "(&(objectClass=posixGroup)"
2596                      "(|(memberUid=%s)(gidNumber=%d)))",
2597                      escape_name, primary_gid);
2598
2599         rc = smbldap_search(conn, lp_ldap_group_suffix(),
2600                             LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg);
2601
2602         if (rc != LDAP_SUCCESS)
2603                 goto done;
2604
2605         num_gids = 0;
2606         *pp_gids = NULL;
2607
2608         num_sids = 0;
2609         *pp_sids = NULL;
2610
2611         /* We need to add the primary group as the first gid/sid */
2612
2613         add_gid_to_array_unique(mem_ctx, primary_gid, pp_gids, &num_gids);
2614
2615         /* This sid will be replaced later */
2616
2617         add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids, &num_sids);
2618
2619         for (entry = ldap_first_entry(conn->ldap_struct, msg);
2620              entry != NULL;
2621              entry = ldap_next_entry(conn->ldap_struct, entry))
2622         {
2623                 fstring str;
2624                 DOM_SID sid;
2625                 gid_t gid;
2626                 char *end;
2627
2628                 if (!smbldap_get_single_attribute(conn->ldap_struct,
2629                                                   entry, "sambaSID",
2630                                                   str, sizeof(str)-1))
2631                         continue;
2632
2633                 if (!string_to_sid(&sid, str))
2634                         goto done;
2635
2636                 if (!smbldap_get_single_attribute(conn->ldap_struct,
2637                                                   entry, "gidNumber",
2638                                                   str, sizeof(str)-1))
2639                         continue;
2640
2641                 gid = strtoul(str, &end, 10);
2642
2643                 if (PTR_DIFF(end, str) != strlen(str))
2644                         goto done;
2645
2646                 if (gid == primary_gid) {
2647                         sid_copy(&(*pp_sids)[0], &sid);
2648                 } else {
2649                         add_gid_to_array_unique(mem_ctx, gid, pp_gids,
2650                                                 &num_gids);
2651                         add_sid_to_array_unique(mem_ctx, &sid, pp_sids,
2652                                                 &num_sids);
2653                 }
2654         }
2655
2656         if (sid_compare(&global_sid_NULL, &(*pp_sids)[0]) == 0) {
2657                 DEBUG(3, ("primary group of [%s] not found\n",
2658                           pdb_get_username(user)));
2659                 goto done;
2660         }
2661
2662         *p_num_groups = num_sids;
2663
2664         result = NT_STATUS_OK;
2665
2666  done:
2667
2668         SAFE_FREE(escape_name);
2669         if (msg != NULL)
2670                 ldap_msgfree(msg);
2671
2672         return result;
2673 }
2674
2675 /**********************************************************************
2676  * Augment a posixGroup object with a sambaGroupMapping domgroup
2677  *********************************************************************/
2678
2679 static NTSTATUS ldapsam_map_posixgroup(TALLOC_CTX *mem_ctx,
2680                                        struct ldapsam_privates *ldap_state,
2681                                        GROUP_MAP *map)
2682 {
2683         const char *filter, *dn;
2684         LDAPMessage *msg, *entry;
2685         LDAPMod **mods;
2686         int rc;
2687
2688         filter = talloc_asprintf(mem_ctx,
2689                                  "(&(objectClass=posixGroup)(gidNumber=%u))",
2690                                  map->gid);
2691         if (filter == NULL) {
2692                 return NT_STATUS_NO_MEMORY;
2693         }
2694
2695         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
2696                                    get_attr_list(mem_ctx, groupmap_attr_list),
2697                                    &msg);
2698         talloc_autofree_ldapmsg(mem_ctx, msg);
2699
2700         if ((rc != LDAP_SUCCESS) ||
2701             (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
2702             ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
2703                 return NT_STATUS_NO_SUCH_GROUP;
2704         }
2705
2706         dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
2707         if (dn == NULL) {
2708                 return NT_STATUS_NO_MEMORY;
2709         }
2710
2711         mods = NULL;
2712         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass",
2713                         "sambaGroupMapping");
2714         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaSid",
2715                          sid_string_static(&map->sid));
2716         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaGroupType",
2717                          talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
2718         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
2719                          map->nt_name);
2720         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
2721                          map->comment);
2722         talloc_autofree_ldapmod(mem_ctx, mods);
2723
2724         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
2725         if (rc != LDAP_SUCCESS) {
2726                 return NT_STATUS_ACCESS_DENIED;
2727         }
2728
2729         return NT_STATUS_OK;
2730 }
2731
2732 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2733                                                 GROUP_MAP *map)
2734 {
2735         struct ldapsam_privates *ldap_state =
2736                 (struct ldapsam_privates *)methods->private_data;
2737         LDAPMessage *msg = NULL;
2738         LDAPMod **mods = NULL;
2739         const char *attrs[] = { NULL };
2740         char *filter;
2741
2742         char *dn;
2743         TALLOC_CTX *mem_ctx;
2744         NTSTATUS result;
2745
2746         DOM_SID sid;
2747
2748         int rc;
2749
2750         mem_ctx = talloc_new(NULL);
2751         if (mem_ctx == NULL) {
2752                 DEBUG(0, ("talloc_new failed\n"));
2753                 return NT_STATUS_NO_MEMORY;
2754         }
2755
2756         filter = talloc_asprintf(mem_ctx, "(sambaSid=%s)",
2757                                  sid_string_static(&map->sid));
2758         if (filter == NULL) {
2759                 result = NT_STATUS_NO_MEMORY;
2760                 goto done;
2761         }
2762
2763         rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
2764                             LDAP_SCOPE_SUBTREE, filter, attrs, True, &msg);
2765         talloc_autofree_ldapmsg(mem_ctx, msg);
2766
2767         if ((rc == LDAP_SUCCESS) &&
2768             (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) > 0)) {
2769
2770                 DEBUG(3, ("SID %s already present in LDAP, refusing to add "
2771                           "group mapping entry\n",
2772                           sid_string_static(&map->sid)));
2773                 result = NT_STATUS_GROUP_EXISTS;
2774                 goto done;
2775         }
2776
2777         switch (map->sid_name_use) {
2778
2779         case SID_NAME_DOM_GRP:
2780                 /* To map a domain group we need to have a posix group
2781                    to attach to. */
2782                 result = ldapsam_map_posixgroup(mem_ctx, ldap_state, map);
2783                 goto done;
2784                 break;
2785
2786         case SID_NAME_ALIAS:
2787                 if (!sid_check_is_in_our_domain(&map->sid)) {
2788                         DEBUG(3, ("Refusing to map sid %s as an alias, not "
2789                                   "in our domain\n",
2790                                   sid_string_static(&map->sid)));
2791                         result = NT_STATUS_INVALID_PARAMETER;
2792                         goto done;
2793                 }
2794                 break;
2795
2796         case SID_NAME_WKN_GRP:
2797                 if (!sid_check_is_in_builtin(&map->sid)) {
2798                         DEBUG(3, ("Refusing to map sid %s as an alias, not "
2799                                   "in builtin domain\n",
2800                                   sid_string_static(&map->sid)));
2801                         result = NT_STATUS_INVALID_PARAMETER;
2802                         goto done;
2803                 }
2804                 break;
2805
2806         default:
2807                 DEBUG(3, ("Got invalid use '%s' for mapping\n",
2808                           sid_type_lookup(map->sid_name_use)));
2809                 result = NT_STATUS_INVALID_PARAMETER;
2810                 goto done;
2811         }
2812
2813         /* Domain groups have been mapped in a separate routine, we have to
2814          * create an alias now */
2815
2816         if (map->gid == -1) {
2817                 DEBUG(10, ("Refusing to map gid==-1\n"));
2818                 result = NT_STATUS_INVALID_PARAMETER;
2819                 goto done;
2820         }
2821
2822         if (pdb_gid_to_sid(map->gid, &sid)) {
2823                 DEBUG(3, ("Gid %d is already mapped to SID %s, refusing to "
2824                           "add\n", map->gid, sid_string_static(&sid)));
2825                 result = NT_STATUS_GROUP_EXISTS;
2826                 goto done;
2827         }
2828
2829         /* Ok, enough checks done. It's still racy to go ahead now, but that's
2830          * the best we can get out of LDAP. */
2831
2832         dn = talloc_asprintf(mem_ctx, "sambaSid=%s,%s",
2833                              sid_string_static(&map->sid),
2834                              lp_ldap_group_suffix());
2835         if (dn == NULL) {
2836                 result = NT_STATUS_NO_MEMORY;
2837                 goto done;
2838         }
2839
2840         mods = NULL;
2841
2842         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
2843                          "sambaSidEntry");
2844         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
2845                          "sambaGroupMapping");
2846
2847         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaSid",
2848                          sid_string_static(&map->sid));
2849         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaGroupType",
2850                          talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
2851         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "displayName",
2852                          map->nt_name);
2853         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "description",
2854                          map->comment);
2855         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "gidNumber",
2856                          talloc_asprintf(mem_ctx, "%u", map->gid));
2857         talloc_autofree_ldapmod(mem_ctx, mods);
2858
2859         rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
2860
2861         result = (rc == LDAP_SUCCESS) ?
2862                 NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
2863
2864  done:
2865         talloc_free(mem_ctx);
2866         return result;
2867 }
2868
2869 /**********************************************************************
2870  * Update a group mapping entry. We're quite strict about what can be changed:
2871  * Only the description and displayname may be changed. It simply does not
2872  * make any sense to change the SID, gid or the type in a mapping.
2873  *********************************************************************/
2874
2875 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
2876                                                    GROUP_MAP *map)
2877 {
2878         struct ldapsam_privates *ldap_state =
2879                 (struct ldapsam_privates *)methods->private_data;
2880         int rc;
2881         const char *filter, *dn;
2882         LDAPMessage *msg = NULL;
2883         LDAPMessage *entry = NULL;
2884         LDAPMod **mods = NULL;
2885         TALLOC_CTX *mem_ctx;
2886         NTSTATUS result;
2887
2888         mem_ctx = talloc_new(NULL);
2889         if (mem_ctx == NULL) {
2890                 DEBUG(0, ("talloc_new failed\n"));
2891                 return NT_STATUS_NO_MEMORY;
2892         }
2893
2894         /* Make 100% sure that sid, gid and type are not changed by looking up
2895          * exactly the values we're given in LDAP. */
2896
2897         filter = talloc_asprintf(mem_ctx, "(&(objectClass=sambaGroupMapping)"
2898                                  "(sambaSid=%s)(gidNumber=%u)"
2899                                  "(sambaGroupType=%d))",
2900                                  sid_string_static(&map->sid), map->gid,
2901                                  map->sid_name_use);
2902         if (filter == NULL) {
2903                 result = NT_STATUS_NO_MEMORY;
2904                 goto done;
2905         }
2906
2907         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
2908                                    get_attr_list(mem_ctx, groupmap_attr_list),
2909                                    &msg);
2910         talloc_autofree_ldapmsg(mem_ctx, msg);
2911
2912         if ((rc != LDAP_SUCCESS) ||
2913             (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
2914             ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
2915                 result = NT_STATUS_NO_SUCH_GROUP;
2916                 goto done;
2917         }
2918
2919         dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
2920
2921         if (dn == NULL) {
2922                 result = NT_STATUS_NO_MEMORY;
2923                 goto done;
2924         }
2925
2926         mods = NULL;
2927         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
2928                          map->nt_name);
2929         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
2930                          map->comment);
2931         talloc_autofree_ldapmod(mem_ctx, mods);
2932
2933         if (mods == NULL) {
2934                 DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: "
2935                           "nothing to do\n"));
2936                 result = NT_STATUS_OK;
2937                 goto done;
2938         }
2939
2940         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
2941
2942         if (rc != LDAP_SUCCESS) {
2943                 result = NT_STATUS_ACCESS_DENIED;
2944                 goto done;
2945         }
2946
2947         DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified "
2948                   "group %lu in LDAP\n", (unsigned long)map->gid));
2949
2950         result = NT_STATUS_OK;
2951
2952  done:
2953         talloc_free(mem_ctx);
2954         return result;
2955 }
2956
2957 /**********************************************************************
2958  *********************************************************************/
2959
2960 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2961                                                    DOM_SID sid)
2962 {
2963         struct ldapsam_privates *priv =
2964                 (struct ldapsam_privates *)methods->private_data;
2965         LDAPMessage *msg, *entry;
2966         int rc;
2967         NTSTATUS result;
2968         TALLOC_CTX *mem_ctx;
2969         char *filter;
2970
2971         mem_ctx = talloc_new(NULL);
2972         if (mem_ctx == NULL) {
2973                 DEBUG(0, ("talloc_new failed\n"));
2974                 return NT_STATUS_NO_MEMORY;
2975         }
2976
2977         filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))",
2978                                  LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID,
2979                                  sid_string_static(&sid));
2980         if (filter == NULL) {
2981                 result = NT_STATUS_NO_MEMORY;
2982                 goto done;
2983         }
2984         rc = smbldap_search_suffix(priv->smbldap_state, filter,
2985                                    get_attr_list(mem_ctx, groupmap_attr_list),
2986                                    &msg);
2987         talloc_autofree_ldapmsg(mem_ctx, msg);
2988
2989         if ((rc != LDAP_SUCCESS) ||
2990             (ldap_count_entries(priv2ld(priv), msg) != 1) ||
2991             ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
2992                 result = NT_STATUS_NO_SUCH_GROUP;
2993                 goto done;
2994         }
2995
2996         rc = ldapsam_delete_entry(priv, mem_ctx, entry, LDAP_OBJ_GROUPMAP,
2997                                   get_attr_list(mem_ctx,
2998                                                 groupmap_attr_list_to_delete));
2999  
3000         if ((rc == LDAP_NAMING_VIOLATION) ||
3001             (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
3002                 const char *attrs[] = { "sambaGroupType", "description",
3003                                         "displayName", "sambaSIDList",
3004                                         NULL };
3005
3006                 /* Second try. Don't delete the sambaSID attribute, this is
3007                    for "old" entries that are tacked on a winbind
3008                    sambaIdmapEntry. */
3009
3010                 rc = ldapsam_delete_entry(priv, mem_ctx, entry,
3011                                           LDAP_OBJ_GROUPMAP, attrs);
3012         }
3013
3014         if ((rc == LDAP_NAMING_VIOLATION) ||
3015             (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
3016                 const char *attrs[] = { "sambaGroupType", "description",
3017                                         "displayName", "sambaSIDList",
3018                                         "gidNumber", NULL };
3019
3020                 /* Third try. This is a post-3.0.21 alias (containing only
3021                  * sambaSidEntry and sambaGroupMapping classes), we also have
3022                  * to delete the gidNumber attribute, only the sambaSidEntry
3023                  * remains */
3024
3025                 rc = ldapsam_delete_entry(priv, mem_ctx, entry,
3026                                           LDAP_OBJ_GROUPMAP, attrs);
3027         }
3028
3029         result = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3030
3031  done:
3032         talloc_free(mem_ctx);
3033         return result;
3034  }
3035
3036 /**********************************************************************
3037  *********************************************************************/
3038
3039 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
3040                                     BOOL update)
3041 {
3042         struct ldapsam_privates *ldap_state =
3043                 (struct ldapsam_privates *)my_methods->private_data;
3044         fstring filter;
3045         int rc;
3046         const char **attr_list;
3047
3048         pstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
3049         attr_list = get_attr_list( NULL, groupmap_attr_list );
3050         rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
3051                             LDAP_SCOPE_SUBTREE, filter,
3052                             attr_list, 0, &ldap_state->result);
3053         talloc_free(attr_list);
3054
3055         if (rc != LDAP_SUCCESS) {
3056                 DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n",
3057                           ldap_err2string(rc)));
3058                 DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n",
3059                           lp_ldap_group_suffix(), filter));
3060                 ldap_msgfree(ldap_state->result);
3061                 ldap_state->result = NULL;
3062                 return NT_STATUS_UNSUCCESSFUL;
3063         }
3064
3065         DEBUG(2, ("ldapsam_setsamgrent: %d entries in the base!\n",
3066                   ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
3067                                      ldap_state->result)));
3068
3069         ldap_state->entry =
3070                 ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
3071                                  ldap_state->result);
3072         ldap_state->index = 0;
3073
3074         return NT_STATUS_OK;
3075 }
3076
3077 /**********************************************************************
3078  *********************************************************************/
3079
3080 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
3081 {
3082         ldapsam_endsampwent(my_methods);
3083 }
3084
3085 /**********************************************************************
3086  *********************************************************************/
3087
3088 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
3089                                     GROUP_MAP *map)
3090 {
3091         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
3092         struct ldapsam_privates *ldap_state =
3093                 (struct ldapsam_privates *)my_methods->private_data;
3094         BOOL bret = False;
3095
3096         while (!bret) {
3097                 if (!ldap_state->entry)
3098                         return ret;
3099                 
3100                 ldap_state->index++;
3101                 bret = init_group_from_ldap(ldap_state, map,
3102                                             ldap_state->entry);
3103                 
3104                 ldap_state->entry =
3105                         ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
3106                                         ldap_state->entry);     
3107         }
3108
3109         return NT_STATUS_OK;
3110 }
3111
3112 /**********************************************************************
3113  *********************************************************************/
3114
3115 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
3116                                            enum SID_NAME_USE sid_name_use,
3117                                            GROUP_MAP **pp_rmap,
3118                                            size_t *p_num_entries,
3119                                            BOOL unix_only)
3120 {
3121         GROUP_MAP map;
3122         GROUP_MAP *mapt;
3123         size_t entries = 0;
3124
3125         *p_num_entries = 0;
3126         *pp_rmap = NULL;
3127
3128         if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
3129                 DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open "
3130                           "passdb\n"));
3131                 return NT_STATUS_ACCESS_DENIED;
3132         }
3133
3134         while (NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, &map))) {
3135                 if (sid_name_use != SID_NAME_UNKNOWN &&
3136                     sid_name_use != map.sid_name_use) {
3137                         DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
3138                                   "not of the requested type\n", map.nt_name));
3139                         continue;
3140                 }
3141                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
3142                         DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
3143                                   "non mapped\n", map.nt_name));
3144                         continue;
3145                 }
3146
3147                 mapt=SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, entries+1);
3148                 if (!mapt) {
3149                         DEBUG(0,("ldapsam_enum_group_mapping: Unable to "
3150                                  "enlarge group map!\n"));
3151                         SAFE_FREE(*pp_rmap);
3152                         return NT_STATUS_UNSUCCESSFUL;
3153                 }
3154                 else
3155                         (*pp_rmap) = mapt;
3156
3157                 mapt[entries] = map;
3158
3159                 entries += 1;
3160
3161         }
3162         ldapsam_endsamgrent(methods);
3163
3164         *p_num_entries = entries;
3165
3166         return NT_STATUS_OK;
3167 }
3168
3169 static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
3170                                         const DOM_SID *alias,
3171                                         const DOM_SID *member,
3172                                         int modop)
3173 {
3174         struct ldapsam_privates *ldap_state =
3175                 (struct ldapsam_privates *)methods->private_data;
3176         char *dn;
3177         LDAPMessage *result = NULL;
3178         LDAPMessage *entry = NULL;
3179         int count;
3180         LDAPMod **mods = NULL;
3181         int rc;
3182         enum SID_NAME_USE type = SID_NAME_USE_NONE;
3183
3184         pstring filter;
3185
3186         if (sid_check_is_in_builtin(alias)) {
3187                 type = SID_NAME_WKN_GRP;
3188         }
3189
3190         if (sid_check_is_in_our_domain(alias)) {
3191                 type = SID_NAME_ALIAS;
3192         }
3193
3194         if (type == SID_NAME_USE_NONE) {
3195                 DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
3196                           sid_string_static(alias)));
3197                 return NT_STATUS_NO_SUCH_ALIAS;
3198         }
3199
3200         pstr_sprintf(filter,
3201                      "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
3202                      LDAP_OBJ_GROUPMAP, sid_string_static(alias),
3203                      type);
3204
3205         if (ldapsam_search_one_group(ldap_state, filter,
3206                                      &result) != LDAP_SUCCESS)
3207                 return NT_STATUS_NO_SUCH_ALIAS;
3208
3209         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
3210                                    result);
3211
3212         if (count < 1) {
3213                 DEBUG(4, ("ldapsam_modify_aliasmem: Did not find alias\n"));
3214                 ldap_msgfree(result);
3215                 return NT_STATUS_NO_SUCH_ALIAS;
3216         }
3217
3218         if (count > 1) {
3219                 DEBUG(1, ("ldapsam_modify_aliasmem: Duplicate entries for "
3220                           "filter %s: count=%d\n", filter, count));
3221                 ldap_msgfree(result);
3222                 return NT_STATUS_NO_SUCH_ALIAS;
3223         }
3224
3225         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
3226                                  result);
3227
3228         if (!entry) {
3229                 ldap_msgfree(result);
3230                 return NT_STATUS_UNSUCCESSFUL;
3231         }
3232
3233         dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
3234         if (!dn) {
3235                 ldap_msgfree(result);
3236                 return NT_STATUS_UNSUCCESSFUL;
3237         }
3238
3239         smbldap_set_mod(&mods, modop,
3240                         get_attr_key2string(groupmap_attr_list,
3241                                             LDAP_ATTR_SID_LIST),
3242                         sid_string_static(member));
3243
3244         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
3245
3246         ldap_mods_free(mods, True);
3247         ldap_msgfree(result);
3248         SAFE_FREE(dn);
3249
3250         if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
3251                 return NT_STATUS_MEMBER_IN_ALIAS;
3252         }
3253
3254         if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
3255                 return NT_STATUS_MEMBER_NOT_IN_ALIAS;
3256         }
3257
3258         if (rc != LDAP_SUCCESS) {
3259                 return NT_STATUS_UNSUCCESSFUL;
3260         }
3261
3262         return NT_STATUS_OK;
3263 }
3264
3265 static NTSTATUS ldapsam_add_aliasmem(struct pdb_methods *methods,
3266                                      const DOM_SID *alias,
3267                                      const DOM_SID *member)
3268 {
3269         return ldapsam_modify_aliasmem(methods, alias, member, LDAP_MOD_ADD);
3270 }
3271
3272 static NTSTATUS ldapsam_del_aliasmem(struct pdb_methods *methods,
3273                                      const DOM_SID *alias,
3274                                      const DOM_SID *member)
3275 {
3276         return ldapsam_modify_aliasmem(methods, alias, member,
3277                                        LDAP_MOD_DELETE);
3278 }
3279
3280 static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
3281                                       const DOM_SID *alias,
3282                                       DOM_SID **pp_members,
3283                                       size_t *p_num_members)
3284 {
3285         struct ldapsam_privates *ldap_state =
3286                 (struct ldapsam_privates *)methods->private_data;
3287         LDAPMessage *result = NULL;
3288         LDAPMessage *entry = NULL;
3289         int count;
3290         char **values;
3291         int i;
3292         pstring filter;
3293         size_t num_members = 0;
3294         enum SID_NAME_USE type = SID_NAME_USE_NONE;
3295
3296         *pp_members = NULL;
3297         *p_num_members = 0;
3298
3299         if (sid_check_is_in_builtin(alias)) {
3300                 type = SID_NAME_WKN_GRP;
3301         }
3302
3303         if (sid_check_is_in_our_domain(alias)) {
3304                 type = SID_NAME_ALIAS;
3305         }
3306
3307         if (type == SID_NAME_USE_NONE) {
3308                 DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
3309                           sid_string_static(alias)));
3310                 return NT_STATUS_NO_SUCH_ALIAS;
3311         }
3312
3313         pstr_sprintf(filter,
3314                      "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
3315                      LDAP_OBJ_GROUPMAP, sid_string_static(alias),
3316                      type);
3317
3318         if (ldapsam_search_one_group(ldap_state, filter,
3319                                      &result) != LDAP_SUCCESS)
3320                 return NT_STATUS_NO_SUCH_ALIAS;
3321
3322         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
3323                                    result);
3324
3325         if (count < 1) {
3326                 DEBUG(4, ("ldapsam_enum_aliasmem: Did not find alias\n"));
3327                 ldap_msgfree(result);
3328                 return NT_STATUS_NO_SUCH_ALIAS;
3329         }
3330
3331         if (count > 1) {
3332                 DEBUG(1, ("ldapsam_enum_aliasmem: Duplicate entries for "
3333                           "filter %s: count=%d\n", filter, count));
3334                 ldap_msgfree(result);
3335                 return NT_STATUS_NO_SUCH_ALIAS;
3336         }
3337
3338         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
3339                                  result);
3340
3341         if (!entry) {
3342                 ldap_msgfree(result);
3343                 return NT_STATUS_UNSUCCESSFUL;
3344         }
3345
3346         values = ldap_get_values(ldap_state->smbldap_state->ldap_struct,
3347                                  entry,
3348                                  get_attr_key2string(groupmap_attr_list,
3349                                                      LDAP_ATTR_SID_LIST));
3350
3351         if (values == NULL) {
3352                 ldap_msgfree(result);
3353                 return NT_STATUS_OK;
3354         }
3355
3356         count = ldap_count_values(values);
3357
3358         for (i=0; i<count; i++) {
3359                 DOM_SID member;
3360
3361                 if (!string_to_sid(&member, values[i]))
3362                         continue;
3363
3364                 add_sid_to_array(NULL, &member, pp_members, &num_members);
3365         }
3366
3367         *p_num_members = num_members;
3368         ldap_value_free(values);
3369         ldap_msgfree(result);
3370
3371         return NT_STATUS_OK;
3372 }
3373
3374 static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
3375                                           TALLOC_CTX *mem_ctx,
3376                                           const DOM_SID *domain_sid,
3377                                           const DOM_SID *members,
3378                                           size_t num_members,
3379                                           uint32 **pp_alias_rids,
3380                                           size_t *p_num_alias_rids)
3381 {
3382         struct ldapsam_privates *ldap_state =
3383                 (struct ldapsam_privates *)methods->private_data;
3384         LDAP *ldap_struct;
3385
3386         const char *attrs[] = { LDAP_ATTRIBUTE_SID, NULL };
3387
3388         LDAPMessage *result = NULL;
3389         LDAPMessage *entry = NULL;
3390         int i;
3391         int rc;
3392         char *filter;
3393         enum SID_NAME_USE type = SID_NAME_USE_NONE;
3394
3395         if (sid_check_is_builtin(domain_sid)) {
3396                 type = SID_NAME_WKN_GRP;
3397         }
3398
3399         if (sid_check_is_domain(domain_sid)) {
3400                 type = SID_NAME_ALIAS;
3401         }
3402
3403         if (type == SID_NAME_USE_NONE) {
3404                 DEBUG(5, ("SID %s is neither builtin nor domain!\n",
3405                           sid_string_static(domain_sid)));
3406                 return NT_STATUS_UNSUCCESSFUL;
3407         }
3408
3409         filter = talloc_asprintf(mem_ctx,
3410                                  "(&(|(objectclass=%s)(sambaGroupType=%d))(|",
3411                                  LDAP_OBJ_GROUPMAP, type);
3412
3413         for (i=0; i<num_members; i++)
3414                 filter = talloc_asprintf(mem_ctx, "%s(sambaSIDList=%s)",
3415                                          filter,
3416                                          sid_string_static(&members[i]));
3417
3418         filter = talloc_asprintf(mem_ctx, "%s))", filter);
3419
3420         rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
3421                             LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
3422
3423         if (rc != LDAP_SUCCESS)
3424                 return NT_STATUS_UNSUCCESSFUL;
3425
3426         ldap_struct = ldap_state->smbldap_state->ldap_struct;
3427
3428         for (entry = ldap_first_entry(ldap_struct, result);
3429              entry != NULL;
3430              entry = ldap_next_entry(ldap_struct, entry))
3431         {
3432                 fstring sid_str;
3433                 DOM_SID sid;
3434                 uint32 rid;
3435
3436                 if (!smbldap_get_single_attribute(ldap_struct, entry,
3437                                                   LDAP_ATTRIBUTE_SID,
3438                                                   sid_str,
3439                                                   sizeof(sid_str)-1))
3440                         continue;
3441
3442                 if (!string_to_sid(&sid, sid_str))
3443                         continue;
3444
3445                 if (!sid_peek_check_rid(domain_sid, &sid, &rid))
3446                         continue;
3447
3448                 add_rid_to_array_unique(mem_ctx, rid, pp_alias_rids,
3449                                         p_num_alias_rids);
3450         }
3451
3452         ldap_msgfree(result);
3453         return NT_STATUS_OK;
3454 }
3455
3456 static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
3457                                                    int policy_index,
3458                                                    uint32 value)
3459 {
3460         NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
3461         int rc;
3462         LDAPMod **mods = NULL;
3463         fstring value_string;
3464         const char *policy_attr = NULL;
3465
3466         struct ldapsam_privates *ldap_state =
3467                 (struct ldapsam_privates *)methods->private_data;
3468
3469         const char *attrs[2];
3470
3471         DEBUG(10,("ldapsam_set_account_policy_in_ldap\n"));
3472
3473         if (!ldap_state->domain_dn) {
3474                 return NT_STATUS_INVALID_PARAMETER;
3475         }
3476
3477         policy_attr = get_account_policy_attr(policy_index);
3478         if (policy_attr == NULL) {
3479                 DEBUG(0,("ldapsam_set_account_policy_in_ldap: invalid "
3480                          "policy\n"));
3481                 return ntstatus;
3482         }
3483
3484         attrs[0] = policy_attr;
3485         attrs[1] = NULL;
3486
3487         slprintf(value_string, sizeof(value_string) - 1, "%i", value);
3488
3489         smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
3490
3491         rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn,
3492                             mods);
3493
3494         ldap_mods_free(mods, True);
3495
3496         if (rc != LDAP_SUCCESS) {
3497                 return ntstatus;
3498         }
3499
3500         if (!cache_account_policy_set(policy_index, value)) {
3501                 DEBUG(0,("ldapsam_set_account_policy_in_ldap: failed to "
3502                          "update local tdb cache\n"));
3503                 return ntstatus;
3504         }
3505
3506         return NT_STATUS_OK;
3507 }
3508
3509 static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods,
3510                                            int policy_index, uint32 value)
3511 {
3512         if (!account_policy_migrated(False)) {
3513                 return (account_policy_set(policy_index, value)) ?
3514                         NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3515         }
3516
3517         return ldapsam_set_account_policy_in_ldap(methods, policy_index,
3518                                                   value);
3519 }
3520
3521 static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods,
3522                                                      int policy_index,
3523                                                      uint32 *value)
3524 {
3525         NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
3526         LDAPMessage *result = NULL;
3527         LDAPMessage *entry = NULL;
3528         int count;
3529         int rc;
3530         char **vals = NULL;
3531         const char *policy_attr = NULL;
3532
3533         struct ldapsam_privates *ldap_state =
3534                 (struct ldapsam_privates *)methods->private_data;
3535
3536         const char *attrs[2];
3537
3538         DEBUG(10,("ldapsam_get_account_policy_from_ldap\n"));
3539
3540         if (!ldap_state->domain_dn) {
3541                 return NT_STATUS_INVALID_PARAMETER;
3542         }
3543
3544         policy_attr = get_account_policy_attr(policy_index);
3545         if (!policy_attr) {
3546                 DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid "
3547                          "policy index: %d\n", policy_index));
3548                 return ntstatus;
3549         }
3550
3551         attrs[0] = policy_attr;
3552         attrs[1] = NULL;
3553
3554         rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn,
3555                             LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0,
3556                             &result);
3557
3558         if (rc != LDAP_SUCCESS) {
3559                 return ntstatus;
3560         }
3561
3562         count = ldap_count_entries(priv2ld(ldap_state), result);
3563         if (count < 1) {
3564                 goto out;
3565         }
3566
3567         entry = ldap_first_entry(priv2ld(ldap_state), result);
3568         if (entry == NULL) {
3569                 goto out;
3570         }
3571
3572         vals = ldap_get_values(priv2ld(ldap_state), entry, policy_attr);
3573         if (vals == NULL) {
3574                 goto out;
3575         }
3576
3577         *value = (uint32)atol(vals[0]);
3578         
3579         ntstatus = NT_STATUS_OK;
3580
3581 out:
3582         if (vals)
3583                 ldap_value_free(vals);
3584         ldap_msgfree(result);
3585
3586         return ntstatus;
3587 }
3588
3589 /* wrapper around ldapsam_get_account_policy_from_ldap(), handles tdb as cache 
3590
3591    - if user hasn't decided to use account policies inside LDAP just reuse the
3592      old tdb values
3593    
3594    - if there is a valid cache entry, return that
3595    - if there is an LDAP entry, update cache and return 
3596    - otherwise set to default, update cache and return
3597
3598    Guenther
3599 */
3600 static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods,
3601                                            int policy_index, uint32 *value)
3602 {
3603         NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
3604
3605         if (!account_policy_migrated(False)) {
3606                 return (account_policy_get(policy_index, value))
3607                         ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3608         }
3609
3610         if (cache_account_policy_get(policy_index, value)) {
3611                 DEBUG(11,("ldapsam_get_account_policy: got valid value from "
3612                           "cache\n"));
3613                 return NT_STATUS_OK;
3614         }
3615
3616         ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index,
3617                                                         value);
3618         if (NT_STATUS_IS_OK(ntstatus)) {
3619                 goto update_cache;
3620         }
3621
3622         DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from "
3623                   "ldap\n"));
3624
3625 #if 0
3626         /* should we automagically migrate old tdb value here ? */
3627         if (account_policy_get(policy_index, value))
3628                 goto update_ldap;
3629
3630         DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying "
3631                   "default\n", policy_index));
3632 #endif
3633
3634         if (!account_policy_get_default(policy_index, value)) {
3635                 return ntstatus;
3636         }
3637         
3638 /* update_ldap: */
3639  
3640         ntstatus = ldapsam_set_account_policy(methods, policy_index, *value);
3641         if (!NT_STATUS_IS_OK(ntstatus)) {
3642                 return ntstatus;
3643         }
3644                 
3645  update_cache:
3646  
3647         if (!cache_account_policy_set(policy_index, *value)) {
3648                 DEBUG(0,("ldapsam_get_account_policy: failed to update local "
3649                          "tdb as a cache\n"));
3650                 return NT_STATUS_UNSUCCESSFUL;
3651         }
3652
3653         return NT_STATUS_OK;
3654 }
3655
3656 static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
3657                                     const DOM_SID *domain_sid,
3658                                     int num_rids,
3659                                     uint32 *rids,
3660                                     const char **names,
3661                                     uint32 *attrs)
3662 {
3663         struct ldapsam_privates *ldap_state =
3664                 (struct ldapsam_privates *)methods->private_data;
3665         LDAPMessage *msg = NULL;
3666         LDAPMessage *entry;
3667         char *allsids = NULL;
3668         int i, rc, num_mapped;
3669         NTSTATUS result = NT_STATUS_NO_MEMORY;
3670         TALLOC_CTX *mem_ctx;
3671         LDAP *ld;
3672         BOOL is_builtin;
3673
3674         mem_ctx = talloc_new(NULL);
3675         if (mem_ctx == NULL) {
3676                 DEBUG(0, ("talloc_new failed\n"));
3677                 goto done;
3678         }
3679
3680         if (!sid_check_is_builtin(domain_sid) &&
3681             !sid_check_is_domain(domain_sid)) {
3682                 result = NT_STATUS_INVALID_PARAMETER;
3683                 goto done;
3684         }
3685
3686         for (i=0; i<num_rids; i++)
3687                 attrs[i] = SID_NAME_UNKNOWN;
3688
3689         allsids = talloc_strdup(mem_ctx, "");
3690         if (allsids == NULL) {
3691                 goto done;
3692         }
3693
3694         for (i=0; i<num_rids; i++) {
3695                 DOM_SID sid;
3696                 sid_copy(&sid, domain_sid);
3697                 sid_append_rid(&sid, rids[i]);
3698                 allsids = talloc_asprintf_append(allsids, "(sambaSid=%s)",
3699                                                  sid_string_static(&sid));
3700                 if (allsids == NULL) {
3701                         goto done;
3702                 }
3703         }
3704
3705         /* First look for users */
3706
3707         {
3708                 char *filter;
3709                 const char *ldap_attrs[] = { "uid", "sambaSid", NULL };
3710
3711                 filter = talloc_asprintf(
3712                         mem_ctx, ("(&(objectClass=sambaSamAccount)(|%s))"),
3713                         allsids);
3714
3715                 if (filter == NULL) {
3716                         goto done;
3717                 }
3718
3719                 rc = smbldap_search(ldap_state->smbldap_state,
3720                                     lp_ldap_user_suffix(),
3721                                     LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
3722                                     &msg);
3723                 talloc_autofree_ldapmsg(mem_ctx, msg);
3724         }
3725
3726         if (rc != LDAP_SUCCESS)
3727                 goto done;
3728
3729         ld = ldap_state->smbldap_state->ldap_struct;
3730         num_mapped = 0;
3731
3732         for (entry = ldap_first_entry(ld, msg);
3733              entry != NULL;
3734              entry = ldap_next_entry(ld, entry)) {
3735                 uint32 rid;
3736                 int rid_index;
3737                 const char *name;
3738
3739                 if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
3740                                                     &rid)) {
3741                         DEBUG(2, ("Could not find sid from ldap entry\n"));
3742                         continue;
3743                 }
3744
3745                 name = smbldap_talloc_single_attribute(ld, entry, "uid",
3746                                                        names);
3747                 if (name == NULL) {
3748                         DEBUG(2, ("Could not retrieve uid attribute\n"));
3749                         continue;
3750                 }
3751
3752                 for (rid_index = 0; rid_index < num_rids; rid_index++) {
3753                         if (rid == rids[rid_index])
3754                                 break;
3755                 }
3756
3757                 if (rid_index == num_rids) {
3758                         DEBUG(2, ("Got a RID not asked for: %d\n", rid));
3759                         continue;
3760                 }
3761
3762                 attrs[rid_index] = SID_NAME_USER;
3763                 names[rid_index] = name;
3764                 num_mapped += 1;
3765         }
3766
3767         if (num_mapped == num_rids) {
3768                 /* No need to look for groups anymore -- we're done */
3769                 result = NT_STATUS_OK;
3770                 goto done;
3771         }
3772
3773         /* Same game for groups */
3774
3775         {
3776                 char *filter;
3777                 const char *ldap_attrs[] = { "cn", "displayName", "sambaSid",
3778                                              "sambaGroupType", NULL };
3779
3780                 filter = talloc_asprintf(
3781                         mem_ctx, "(&(objectClass=sambaGroupMapping)(|%s))",
3782                         allsids);
3783                 if (filter == NULL) {
3784                         goto done;
3785                 }
3786
3787                 rc = smbldap_search(ldap_state->smbldap_state,
3788                                     lp_ldap_group_suffix(),
3789                                     LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
3790                                     &msg);
3791                 talloc_autofree_ldapmsg(mem_ctx, msg);
3792         }
3793
3794         if (rc != LDAP_SUCCESS)
3795                 goto done;
3796
3797         /* ldap_struct might have changed due to a reconnect */
3798
3799         ld = ldap_state->smbldap_state->ldap_struct;
3800
3801         /* For consistency checks, we already checked we're only domain or builtin */
3802
3803         is_builtin = sid_check_is_builtin(domain_sid);
3804
3805         for (entry = ldap_first_entry(ld, msg);
3806              entry != NULL;
3807              entry = ldap_next_entry(ld, entry))
3808         {
3809                 uint32 rid;
3810                 int rid_index;
3811                 const char *attr;
3812                 enum SID_NAME_USE type;
3813                 const char *dn = smbldap_talloc_dn(mem_ctx, ld, entry);
3814
3815                 attr = smbldap_talloc_single_attribute(ld, entry, "sambaGroupType",
3816                                                        mem_ctx);
3817                 if (attr == NULL) {
3818                         DEBUG(2, ("Could not extract type from ldap entry %s\n",
3819                                   dn));
3820                         continue;
3821                 }
3822
3823                 type = atol(attr);
3824
3825                 /* Consistency checks */
3826                 if ((is_builtin && (type != SID_NAME_WKN_GRP)) ||
3827                     (!is_builtin && ((type != SID_NAME_ALIAS) &&
3828                                      (type != SID_NAME_DOM_GRP)))) {
3829                         DEBUG(2, ("Rejecting invalid group mapping entry %s\n", dn));
3830                 }
3831
3832                 if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
3833                                                     &rid)) {
3834                         DEBUG(2, ("Could not find sid from ldap entry %s\n", dn));
3835                         continue;
3836                 }
3837
3838                 attr = smbldap_talloc_single_attribute(ld, entry, "cn", names);
3839
3840                 if (attr == NULL) {
3841                         DEBUG(10, ("Could not retrieve 'cn' attribute from %s\n",
3842                                    dn));
3843                         attr = smbldap_talloc_single_attribute(
3844                                 ld, entry, "displayName", names);
3845                 }
3846
3847                 if (attr == NULL) {
3848                         DEBUG(2, ("Could not retrieve naming attribute from %s\n",
3849                                   dn));
3850                         continue;
3851                 }
3852
3853                 for (rid_index = 0; rid_index < num_rids; rid_index++) {
3854                         if (rid == rids[rid_index])
3855                                 break;
3856                 }
3857
3858                 if (rid_index == num_rids) {
3859                         DEBUG(2, ("Got a RID not asked for: %d\n", rid));
3860                         continue;
3861                 }
3862
3863                 attrs[rid_index] = type;
3864                 names[rid_index] = attr;
3865                 num_mapped += 1;
3866         }
3867
3868         result = NT_STATUS_NONE_MAPPED;
3869
3870         if (num_mapped > 0)
3871                 result = (num_mapped == num_rids) ?
3872                         NT_STATUS_OK : STATUS_SOME_UNMAPPED;
3873  done:
3874         talloc_free(mem_ctx);
3875         return result;
3876 }
3877
3878 static char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username)
3879 {
3880         char *filter = NULL;
3881         char *escaped = NULL;
3882         char *result = NULL;
3883
3884         asprintf(&filter, "(&%s(objectclass=sambaSamAccount))",
3885                  "(uid=%u)");
3886         if (filter == NULL) goto done;
3887
3888         escaped = escape_ldap_string_alloc(username);
3889         if (escaped == NULL) goto done;
3890
3891         result = talloc_string_sub(mem_ctx, filter, "%u", username);
3892
3893  done:
3894         SAFE_FREE(filter);
3895         SAFE_FREE(escaped);
3896
3897         return result;
3898 }
3899
3900 const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...)
3901 {
3902         int i, num = 0;
3903         va_list ap;
3904         const char **result;
3905
3906         va_start(ap, mem_ctx);
3907         while (va_arg(ap, const char *) != NULL)
3908                 num += 1;
3909         va_end(ap);
3910
3911         result = TALLOC_ARRAY(mem_ctx, const char *, num+1);
3912
3913         va_start(ap, mem_ctx);
3914         for (i=0; i<num; i++)
3915                 result[i] = talloc_strdup(mem_ctx, va_arg(ap, const char*));
3916         va_end(ap);
3917
3918         result[num] = NULL;
3919         return result;
3920 }
3921
3922 struct ldap_search_state {
3923         struct smbldap_state *connection;
3924
3925         uint16 acct_flags;
3926         uint16 group_type;
3927
3928         const char *base;
3929         int scope;
3930         const char *filter;
3931         const char **attrs;
3932         int attrsonly;
3933         void *pagedresults_cookie;
3934
3935         LDAPMessage *entries, *current_entry;
3936         BOOL (*ldap2displayentry)(struct ldap_search_state *state,
3937                                   TALLOC_CTX *mem_ctx,
3938                                   LDAP *ld, LDAPMessage *entry,
3939                                   struct samr_displayentry *result);
3940 };
3941
3942 static BOOL ldapsam_search_firstpage(struct pdb_search *search)
3943 {
3944         struct ldap_search_state *state = search->private_data;
3945         LDAP *ld;
3946         int rc = LDAP_OPERATIONS_ERROR;
3947
3948         state->entries = NULL;
3949
3950         if (state->connection->paged_results) {
3951                 rc = smbldap_search_paged(state->connection, state->base,
3952                                           state->scope, state->filter,
3953                                           state->attrs, state->attrsonly,
3954                                           lp_ldap_page_size(), &state->entries,
3955                                           &state->pagedresults_cookie);
3956         }
3957
3958         if ((rc != LDAP_SUCCESS) || (state->entries == NULL)) {
3959
3960                 if (state->entries != NULL) {
3961                         /* Left over from unsuccessful paged attempt */
3962                         ldap_msgfree(state->entries);
3963                         state->entries = NULL;
3964                 }
3965
3966                 rc = smbldap_search(state->connection, state->base,
3967                                     state->scope, state->filter, state->attrs,
3968                                     state->attrsonly, &state->entries);
3969
3970                 if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
3971                         return False;
3972
3973                 /* Ok, the server was lying. It told us it could do paged
3974                  * searches when it could not. */
3975                 state->connection->paged_results = False;
3976         }
3977
3978         ld = state->connection->ldap_struct;
3979         if ( ld == NULL) {
3980                 DEBUG(5, ("Don't have an LDAP connection right after a "
3981                           "search\n"));
3982                 return False;
3983         }
3984         state->current_entry = ldap_first_entry(ld, state->entries);
3985
3986         if (state->current_entry == NULL) {
3987                 ldap_msgfree(state->entries);
3988                 state->entries = NULL;
3989         }
3990
3991         return True;
3992 }
3993
3994 static BOOL ldapsam_search_nextpage(struct pdb_search *search)
3995 {
3996         struct ldap_search_state *state = search->private_data;
3997         int rc;
3998
3999         if (!state->connection->paged_results) {
4000                 /* There is no next page when there are no paged results */
4001                 return False;
4002         }
4003
4004         rc = smbldap_search_paged(state->connection, state->base,
4005                                   state->scope, state->filter, state->attrs,
4006                                   state->attrsonly, lp_ldap_page_size(),
4007                                   &state->entries,
4008                                   &state->pagedresults_cookie);
4009
4010         if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
4011                 return False;
4012
4013         state->current_entry = ldap_first_entry(state->connection->ldap_struct, state->entries);
4014
4015         if (state->current_entry == NULL) {
4016                 ldap_msgfree(state->entries);
4017                 state->entries = NULL;
4018         }
4019
4020         return True;
4021 }
4022
4023 static BOOL ldapsam_search_next_entry(struct pdb_search *search,
4024                                       struct samr_displayentry *entry)
4025 {
4026         struct ldap_search_state *state = search->private_data;
4027         BOOL result;
4028
4029  retry:
4030         if ((state->entries == NULL) && (state->pagedresults_cookie == NULL))
4031                 return False;
4032
4033         if ((state->entries == NULL) &&
4034             !ldapsam_search_nextpage(search))
4035                     return False;
4036
4037         result = state->ldap2displayentry(state, search->mem_ctx, state->connection->ldap_struct,
4038                                           state->current_entry, entry);
4039
4040         if (!result) {
4041                 char *dn;
4042                 dn = ldap_get_dn(state->connection->ldap_struct, state->current_entry);
4043                 DEBUG(5, ("Skipping entry %s\n", dn != NULL ? dn : "<NULL>"));
4044                 if (dn != NULL) ldap_memfree(dn);
4045         }
4046
4047         state->current_entry = ldap_next_entry(state->connection->ldap_struct, state->current_entry);
4048
4049         if (state->current_entry == NULL) {
4050                 ldap_msgfree(state->entries);
4051                 state->entries = NULL;
4052         }
4053
4054         if (!result) goto retry;
4055
4056         return True;
4057 }
4058
4059 static void ldapsam_search_end(struct pdb_search *search)
4060 {
4061         struct ldap_search_state *state = search->private_data;
4062         int rc;
4063
4064         if (state->pagedresults_cookie == NULL)
4065                 return;
4066
4067         if (state->entries != NULL)
4068                 ldap_msgfree(state->entries);
4069
4070         state->entries = NULL;
4071         state->current_entry = NULL;
4072
4073         if (!state->connection->paged_results)
4074                 return;
4075
4076         /* Tell the LDAP server we're not interested in the rest anymore. */
4077
4078         rc = smbldap_search_paged(state->connection, state->base, state->scope,
4079                                   state->filter, state->attrs,
4080                                   state->attrsonly, 0, &state->entries,
4081                                   &state->pagedresults_cookie);
4082
4083         if (rc != LDAP_SUCCESS)
4084                 DEBUG(5, ("Could not end search properly\n"));
4085
4086         return;
4087 }
4088
4089 static BOOL ldapuser2displayentry(struct ldap_search_state *state,
4090                                   TALLOC_CTX *mem_ctx,
4091                                   LDAP *ld, LDAPMessage *entry,
4092                                   struct samr_displayentry *result)
4093 {
4094         char **vals;
4095         DOM_SID sid;
4096         uint16 acct_flags;
4097
4098         vals = ldap_get_values(ld, entry, "sambaAcctFlags");
4099         if ((vals == NULL) || (vals[0] == NULL)) {
4100                 DEBUG(5, ("\"sambaAcctFlags\" not found\n"));
4101                 return False;
4102         }
4103         acct_flags = pdb_decode_acct_ctrl(vals[0]);
4104         ldap_value_free(vals);
4105
4106         if ((state->acct_flags != 0) &&
4107             ((state->acct_flags & acct_flags) == 0))
4108                 return False;           
4109
4110         result->acct_flags = acct_flags;
4111         result->account_name = "";
4112         result->fullname = "";
4113         result->description = "";
4114
4115         vals = ldap_get_values(ld, entry, "uid");
4116         if ((vals == NULL) || (vals[0] == NULL)) {
4117                 DEBUG(5, ("\"uid\" not found\n"));
4118                 return False;
4119         }
4120         pull_utf8_talloc(mem_ctx,
4121                          CONST_DISCARD(char **, &result->account_name),
4122                          vals[0]);
4123         ldap_value_free(vals);
4124
4125         vals = ldap_get_values(ld, entry, "displayName");
4126         if ((vals == NULL) || (vals[0] == NULL))
4127                 DEBUG(8, ("\"displayName\" not found\n"));
4128         else
4129                 pull_utf8_talloc(mem_ctx,
4130                                  CONST_DISCARD(char **, &result->fullname),
4131                                  vals[0]);
4132         ldap_value_free(vals);
4133
4134         vals = ldap_get_values(ld, entry, "description");
4135         if ((vals == NULL) || (vals[0] == NULL))
4136                 DEBUG(8, ("\"description\" not found\n"));
4137         else
4138                 pull_utf8_talloc(mem_ctx,
4139                                  CONST_DISCARD(char **, &result->description),
4140                                  vals[0]);
4141         ldap_value_free(vals);
4142
4143         if ((result->account_name == NULL) ||
4144             (result->fullname == NULL) ||
4145             (result->description == NULL)) {
4146                 DEBUG(0, ("talloc failed\n"));
4147                 return False;
4148         }
4149         
4150         vals = ldap_get_values(ld, entry, "sambaSid");
4151         if ((vals == NULL) || (vals[0] == NULL)) {
4152                 DEBUG(0, ("\"objectSid\" not found\n"));
4153                 return False;
4154         }
4155
4156         if (!string_to_sid(&sid, vals[0])) {
4157                 DEBUG(0, ("Could not convert %s to SID\n", vals[0]));
4158                 ldap_value_free(vals);
4159                 return False;
4160         }
4161         ldap_value_free(vals);
4162
4163         if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
4164                 DEBUG(0, ("sid %s does not belong to our domain\n",
4165                           sid_string_static(&sid)));
4166                 return False;
4167         }
4168
4169         return True;
4170 }
4171
4172
4173 static BOOL ldapsam_search_users(struct pdb_methods *methods,
4174                                  struct pdb_search *search,
4175                                  uint16 acct_flags)
4176 {
4177         struct ldapsam_privates *ldap_state = methods->private_data;
4178         struct ldap_search_state *state;
4179
4180         state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
4181         if (state == NULL) {
4182                 DEBUG(0, ("talloc failed\n"));
4183                 return False;
4184         }
4185
4186         state->connection = ldap_state->smbldap_state;
4187
4188         if ((acct_flags != 0) && ((acct_flags & ACB_NORMAL) != 0))
4189                 state->base = lp_ldap_user_suffix();
4190         else if ((acct_flags != 0) &&
4191                  ((acct_flags & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) != 0))
4192                 state->base = lp_ldap_machine_suffix();
4193         else
4194                 state->base = lp_ldap_suffix();
4195
4196         state->acct_flags = acct_flags;
4197         state->base = talloc_strdup(search->mem_ctx, state->base);
4198         state->scope = LDAP_SCOPE_SUBTREE;
4199         state->filter = get_ldap_filter(search->mem_ctx, "*");
4200         state->attrs = talloc_attrs(search->mem_ctx, "uid", "sambaSid",
4201                                     "displayName", "description",
4202                                     "sambaAcctFlags", NULL);
4203         state->attrsonly = 0;
4204         state->pagedresults_cookie = NULL;
4205         state->entries = NULL;
4206         state->ldap2displayentry = ldapuser2displayentry;
4207
4208         if ((state->filter == NULL) || (state->attrs == NULL)) {
4209                 DEBUG(0, ("talloc failed\n"));
4210                 return False;
4211         }
4212
4213         search->private_data = state;
4214         search->next_entry = ldapsam_search_next_entry;
4215         search->search_end = ldapsam_search_end;
4216
4217         return ldapsam_search_firstpage(search);
4218 }
4219
4220 static BOOL ldapgroup2displayentry(struct ldap_search_state *state,
4221                                    TALLOC_CTX *mem_ctx,
4222                                    LDAP *ld, LDAPMessage *entry,
4223                                    struct samr_displayentry *result)
4224 {
4225         char **vals;
4226         DOM_SID sid;
4227         uint16 group_type;
4228
4229         result->account_name = "";
4230         result->fullname = "";
4231         result->description = "";
4232
4233
4234         vals = ldap_get_values(ld, entry, "sambaGroupType");
4235         if ((vals == NULL) || (vals[0] == NULL)) {
4236                 DEBUG(5, ("\"sambaGroupType\" not found\n"));
4237                 if (vals != NULL) {
4238                         ldap_value_free(vals);
4239                 }
4240                 return False;
4241         }
4242
4243         group_type = atoi(vals[0]);
4244
4245         if ((state->group_type != 0) &&
4246             ((state->group_type != group_type))) {
4247                 ldap_value_free(vals);
4248                 return False;
4249         }
4250
4251         ldap_value_free(vals);
4252
4253         /* display name is the NT group name */
4254
4255         vals = ldap_get_values(ld, entry, "displayName");
4256         if ((vals == NULL) || (vals[0] == NULL)) {
4257                 DEBUG(8, ("\"displayName\" not found\n"));
4258
4259                 /* fallback to the 'cn' attribute */
4260                 vals = ldap_get_values(ld, entry, "cn");
4261                 if ((vals == NULL) || (vals[0] == NULL)) {
4262                         DEBUG(5, ("\"cn\" not found\n"));
4263                         return False;
4264                 }
4265                 pull_utf8_talloc(mem_ctx,
4266                                  CONST_DISCARD(char **, &result->account_name),
4267                                  vals[0]);
4268         }
4269         else {
4270                 pull_utf8_talloc(mem_ctx,
4271                                  CONST_DISCARD(char **, &result->account_name),
4272                                  vals[0]);
4273         }
4274
4275         ldap_value_free(vals);
4276
4277         vals = ldap_get_values(ld, entry, "description");
4278         if ((vals == NULL) || (vals[0] == NULL))
4279                 DEBUG(8, ("\"description\" not found\n"));
4280         else
4281                 pull_utf8_talloc(mem_ctx,
4282                                  CONST_DISCARD(char **, &result->description),
4283                                  vals[0]);
4284         ldap_value_free(vals);
4285
4286         if ((result->account_name == NULL) ||
4287             (result->fullname == NULL) ||
4288             (result->description == NULL)) {
4289                 DEBUG(0, ("talloc failed\n"));
4290                 return False;
4291         }
4292         
4293         vals = ldap_get_values(ld, entry, "sambaSid");
4294         if ((vals == NULL) || (vals[0] == NULL)) {
4295                 DEBUG(0, ("\"objectSid\" not found\n"));
4296                 if (vals != NULL) {
4297                         ldap_value_free(vals);
4298                 }
4299                 return False;
4300         }
4301
4302         if (!string_to_sid(&sid, vals[0])) {
4303                 DEBUG(0, ("Could not convert %s to SID\n", vals[0]));
4304                 return False;
4305         }
4306
4307         ldap_value_free(vals);
4308
4309         switch (group_type) {
4310                 case SID_NAME_DOM_GRP:
4311                 case SID_NAME_ALIAS:
4312
4313                         if (!sid_peek_check_rid(get_global_sam_sid(), &sid,
4314                                                 &result->rid)) {
4315                                 DEBUG(0, ("%s is not in our domain\n",
4316                                           sid_string_static(&sid)));
4317                                 return False;
4318                         }
4319                         break;
4320         
4321                 case SID_NAME_WKN_GRP:
4322
4323                         if (!sid_peek_check_rid(&global_sid_Builtin, &sid,
4324                                                 &result->rid)) {
4325
4326                                 DEBUG(0, ("%s is not in builtin sid\n",
4327                                           sid_string_static(&sid)));
4328                                 return False;
4329                         }
4330                         break;
4331
4332                 default:
4333                         DEBUG(0,("unkown group type: %d\n", group_type));
4334                         return False;
4335         }
4336         
4337         return True;
4338 }
4339
4340 static BOOL ldapsam_search_grouptype(struct pdb_methods *methods,
4341                                      struct pdb_search *search,
4342                                      enum SID_NAME_USE type)
4343 {
4344         struct ldapsam_privates *ldap_state = methods->private_data;
4345         struct ldap_search_state *state;
4346
4347         state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
4348         if (state == NULL) {
4349                 DEBUG(0, ("talloc failed\n"));
4350                 return False;
4351         }
4352
4353         state->connection = ldap_state->smbldap_state;
4354
4355         state->base = talloc_strdup(search->mem_ctx, lp_ldap_group_suffix());
4356         state->connection = ldap_state->smbldap_state;
4357         state->scope = LDAP_SCOPE_SUBTREE;
4358         state->filter = talloc_asprintf(search->mem_ctx,
4359                                         "(&(objectclass=sambaGroupMapping)"
4360                                         "(sambaGroupType=%d))", type);
4361         state->attrs = talloc_attrs(search->mem_ctx, "cn", "sambaSid",
4362                                     "displayName", "description",
4363                                     "sambaGroupType", NULL);
4364         state->attrsonly = 0;
4365         state->pagedresults_cookie = NULL;
4366         state->entries = NULL;
4367         state->group_type = type;
4368         state->ldap2displayentry = ldapgroup2displayentry;
4369
4370         if ((state->filter == NULL) || (state->attrs == NULL)) {
4371                 DEBUG(0, ("talloc failed\n"));
4372                 return False;
4373         }
4374
4375         search->private_data = state;
4376         search->next_entry = ldapsam_search_next_entry;
4377         search->search_end = ldapsam_search_end;
4378
4379         return ldapsam_search_firstpage(search);
4380 }
4381
4382 static BOOL ldapsam_search_groups(struct pdb_methods *methods,
4383                                   struct pdb_search *search)
4384 {
4385         return ldapsam_search_grouptype(methods, search, SID_NAME_DOM_GRP);
4386 }
4387
4388 static BOOL ldapsam_search_aliases(struct pdb_methods *methods,
4389                                    struct pdb_search *search,
4390                                    const DOM_SID *sid)
4391 {
4392         if (sid_check_is_domain(sid))
4393                 return ldapsam_search_grouptype(methods, search,
4394                                                 SID_NAME_ALIAS);
4395
4396         if (sid_check_is_builtin(sid))
4397                 return ldapsam_search_grouptype(methods, search,
4398                                                 SID_NAME_WKN_GRP);
4399
4400         DEBUG(5, ("Don't know SID %s\n", sid_string_static(sid)));
4401         return False;
4402 }
4403
4404 static BOOL ldapsam_rid_algorithm(struct pdb_methods *methods)
4405 {
4406         return False;
4407 }
4408
4409 static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
4410                                     uint32 *rid)
4411 {
4412         struct smbldap_state *smbldap_state = priv->smbldap_state;
4413
4414         LDAPMessage *result = NULL;
4415         LDAPMessage *entry = NULL;
4416         LDAPMod **mods = NULL;
4417         NTSTATUS status;
4418         char *value;
4419         int rc;
4420         uint32 nextRid = 0;
4421
4422         TALLOC_CTX *mem_ctx;
4423
4424         mem_ctx = talloc_new(NULL);
4425         if (mem_ctx == NULL) {
4426                 DEBUG(0, ("talloc_new failed\n"));
4427                 return NT_STATUS_NO_MEMORY;
4428         }
4429
4430         status = smbldap_search_domain_info(smbldap_state, &result,
4431                                             get_global_sam_name(), False);
4432         if (!NT_STATUS_IS_OK(status)) {
4433                 DEBUG(3, ("Could not get domain info: %s\n",
4434                           nt_errstr(status)));
4435                 goto done;
4436         }
4437
4438         talloc_autofree_ldapmsg(mem_ctx, result);
4439
4440         entry = ldap_first_entry(priv2ld(priv), result);
4441         if (entry == NULL) {
4442                 DEBUG(0, ("Could not get domain info entry\n"));
4443                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4444                 goto done;
4445         }
4446
4447         /* Find the largest of the three attributes "sambaNextRid",
4448            "sambaNextGroupRid" and "sambaNextUserRid". I gave up on the
4449            concept of differentiating between user and group rids, and will
4450            use only "sambaNextRid" in the future. But for compatibility
4451            reasons I look if others have chosen different strategies -- VL */
4452
4453         value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
4454                                                 "sambaNextRid", mem_ctx);
4455         if (value != NULL) {
4456                 uint32 tmp = (uint32)strtoul(value, NULL, 10);
4457                 nextRid = MAX(nextRid, tmp);
4458         }
4459
4460         value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
4461                                                 "sambaNextUserRid", mem_ctx);
4462         if (value != NULL) {
4463                 uint32 tmp = (uint32)strtoul(value, NULL, 10);
4464                 nextRid = MAX(nextRid, tmp);
4465         }
4466
4467         value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
4468                                                 "sambaNextGroupRid", mem_ctx);
4469         if (value != NULL) {
4470                 uint32 tmp = (uint32)strtoul(value, NULL, 10);
4471                 nextRid = MAX(nextRid, tmp);
4472         }
4473
4474         if (nextRid == 0) {
4475                 nextRid = BASE_RID-1;
4476         }
4477
4478         nextRid += 1;
4479
4480         smbldap_make_mod(priv2ld(priv), entry, &mods, "sambaNextRid",
4481                          talloc_asprintf(mem_ctx, "%d", nextRid));
4482         talloc_autofree_ldapmod(mem_ctx, mods);
4483
4484         rc = smbldap_modify(smbldap_state,
4485                             smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry),
4486                             mods);
4487
4488         /* ACCESS_DENIED is used as a placeholder for "the modify failed,
4489          * please retry" */
4490
4491         status = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
4492
4493  done:
4494         if (NT_STATUS_IS_OK(status)) {
4495                 *rid = nextRid;
4496         }
4497
4498         talloc_free(mem_ctx);
4499         return status;
4500 }
4501
4502 static BOOL ldapsam_new_rid(struct pdb_methods *methods, uint32 *rid)
4503 {
4504         int i;
4505
4506         for (i=0; i<10; i++) {
4507                 NTSTATUS result = ldapsam_get_new_rid(methods->private_data,
4508                                                       rid);
4509                 if (NT_STATUS_IS_OK(result)) {
4510                         return True;
4511                 }
4512
4513                 if (!NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
4514                         return False;
4515                 }
4516
4517                 /* The ldap update failed (maybe a race condition), retry */
4518         }
4519
4520         /* Tried 10 times, fail. */
4521         return False;
4522 }
4523
4524 static BOOL ldapsam_sid_to_id(struct pdb_methods *methods,
4525                               const DOM_SID *sid,
4526                               union unid_t *id, enum SID_NAME_USE *type)
4527 {
4528         struct ldapsam_privates *priv = methods->private_data;
4529         char *filter;
4530         const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber",
4531                                 NULL };
4532         LDAPMessage *result = NULL;
4533         LDAPMessage *entry = NULL;
4534         BOOL ret = False;
4535         char *value;
4536         int rc;
4537
4538         TALLOC_CTX *mem_ctx;
4539
4540         mem_ctx = talloc_new(NULL);
4541         if (mem_ctx == NULL) {
4542                 DEBUG(0, ("talloc_new failed\n"));
4543                 return False;
4544         }
4545
4546         filter = talloc_asprintf(mem_ctx,
4547                                  "(&(sambaSid=%s)"
4548                                  "(|(objectClass=sambaGroupMapping)"
4549                                  "(objectClass=sambaSamAccount)))",
4550                                  sid_string_static(sid));
4551         if (filter == NULL) {
4552                 DEBUG(5, ("talloc_asprintf failed\n"));
4553                 goto done;
4554         }
4555
4556         rc = smbldap_search_suffix(priv->smbldap_state, filter,
4557                                    attrs, &result);
4558         if (rc != LDAP_SUCCESS) {
4559                 goto done;
4560         }
4561         talloc_autofree_ldapmsg(mem_ctx, result);
4562
4563         if (ldap_count_entries(priv2ld(priv), result) != 1) {
4564                 DEBUG(10, ("Got %d entries, expected one\n",
4565                            ldap_count_entries(priv2ld(priv), result)));
4566                 goto done;
4567         }
4568
4569         entry = ldap_first_entry(priv2ld(priv), result);
4570
4571         value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
4572                                                 "sambaGroupType", mem_ctx);
4573
4574         if (value != NULL) {
4575                 const char *gid_str;
4576                 /* It's a group */
4577
4578                 gid_str = smbldap_talloc_single_attribute(
4579                         priv2ld(priv), entry, "gidNumber", mem_ctx);
4580                 if (gid_str == NULL) {
4581                         DEBUG(1, ("%s has sambaGroupType but no gidNumber\n",
4582                                   smbldap_talloc_dn(mem_ctx, priv2ld(priv),
4583                                                     entry)));
4584                         goto done;
4585                 }
4586
4587                 id->gid = strtoul(gid_str, NULL, 10);
4588                 *type = strtoul(value, NULL, 10);
4589                 ret = True;
4590                 goto done;
4591         }
4592
4593         /* It must be a user */
4594
4595         value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
4596                                                 "uidNumber", mem_ctx);
4597         if (value == NULL) {
4598                 DEBUG(1, ("Could not find uidNumber in %s\n",
4599                           smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry)));
4600                 goto done;
4601         }
4602
4603         id->uid = strtoul(value, NULL, 10);
4604         *type = SID_NAME_USER;
4605
4606         ret = True;
4607  done:
4608         talloc_free(mem_ctx);
4609         return ret;
4610 }
4611
4612 /**********************************************************************
4613  Housekeeping
4614  *********************************************************************/
4615
4616 static void free_private_data(void **vp) 
4617 {
4618         struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
4619
4620         smbldap_free_struct(&(*ldap_state)->smbldap_state);
4621
4622         if ((*ldap_state)->result != NULL) {
4623                 ldap_msgfree((*ldap_state)->result);
4624                 (*ldap_state)->result = NULL;
4625         }
4626         if ((*ldap_state)->domain_dn != NULL) {
4627                 SAFE_FREE((*ldap_state)->domain_dn);
4628         }
4629
4630         *ldap_state = NULL;
4631
4632         /* No need to free any further, as it is talloc()ed */
4633 }
4634
4635 /**********************************************************************
4636  Intitalise the parts of the pdb_context that are common to all pdb_ldap modes
4637  *********************************************************************/
4638
4639 static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, 
4640                                         const char *location)
4641 {
4642         NTSTATUS nt_status;
4643         struct ldapsam_privates *ldap_state;
4644
4645         if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
4646                 return nt_status;
4647         }
4648
4649         (*pdb_method)->name = "ldapsam";
4650
4651         (*pdb_method)->setsampwent = ldapsam_setsampwent;
4652         (*pdb_method)->endsampwent = ldapsam_endsampwent;
4653         (*pdb_method)->getsampwent = ldapsam_getsampwent;
4654         (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
4655         (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
4656         (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
4657         (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
4658         (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
4659         (*pdb_method)->rename_sam_account = ldapsam_rename_sam_account;
4660
4661         (*pdb_method)->getgrsid = ldapsam_getgrsid;
4662         (*pdb_method)->getgrgid = ldapsam_getgrgid;
4663         (*pdb_method)->getgrnam = ldapsam_getgrnam;
4664         (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
4665         (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
4666         (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
4667         (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
4668
4669         (*pdb_method)->get_account_policy = ldapsam_get_account_policy;
4670         (*pdb_method)->set_account_policy = ldapsam_set_account_policy;
4671
4672         (*pdb_method)->get_seq_num = ldapsam_get_seq_num;
4673
4674         (*pdb_method)->rid_algorithm = ldapsam_rid_algorithm;
4675         (*pdb_method)->new_rid = ldapsam_new_rid;
4676
4677         /* TODO: Setup private data and free */
4678
4679         ldap_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct ldapsam_privates);
4680         if (!ldap_state) {
4681                 DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n"));
4682                 return NT_STATUS_NO_MEMORY;
4683         }
4684
4685         if (!NT_STATUS_IS_OK(nt_status = 
4686                              smbldap_init(pdb_context->mem_ctx, location, 
4687                                           &ldap_state->smbldap_state)));
4688
4689         ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
4690         if (!ldap_state->domain_name) {
4691                 return NT_STATUS_NO_MEMORY;
4692         }
4693
4694         (*pdb_method)->private_data = ldap_state;
4695
4696         (*pdb_method)->free_private_data = free_private_data;
4697
4698         return NT_STATUS_OK;
4699 }
4700
4701 /**********************************************************************
4702  Initialise the 'compat' mode for pdb_ldap
4703  *********************************************************************/
4704
4705 NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
4706 {
4707         NTSTATUS nt_status;
4708         struct ldapsam_privates *ldap_state;
4709
4710 #ifdef WITH_LDAP_SAMCONFIG
4711         if (!location) {
4712                 int ldap_port = lp_ldap_port();
4713                         
4714                 /* remap default port if not using SSL (ie clear or TLS) */
4715                 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
4716                         ldap_port = 389;
4717                 }
4718
4719                 location = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
4720                 if (!location) {
4721                         return NT_STATUS_NO_MEMORY;
4722                 }
4723         }
4724 #endif
4725
4726         if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
4727                 return nt_status;
4728         }
4729
4730         (*pdb_method)->name = "ldapsam_compat";
4731
4732         ldap_state = (*pdb_method)->private_data;
4733         ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
4734
4735         sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
4736
4737         return NT_STATUS_OK;
4738 }
4739
4740 /**********************************************************************
4741  Initialise the normal mode for pdb_ldap
4742  *********************************************************************/
4743
4744 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
4745 {
4746         NTSTATUS nt_status;
4747         struct ldapsam_privates *ldap_state;
4748         uint32 alg_rid_base;
4749         pstring alg_rid_base_string;
4750         LDAPMessage *result = NULL;
4751         LDAPMessage *entry = NULL;
4752         DOM_SID ldap_domain_sid;
4753         DOM_SID secrets_domain_sid;
4754         pstring domain_sid_string;
4755         char *dn;
4756
4757         nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location);
4758         if (!NT_STATUS_IS_OK(nt_status)) {
4759                 return nt_status;
4760         }
4761
4762         (*pdb_method)->name = "ldapsam";
4763
4764         (*pdb_method)->add_aliasmem = ldapsam_add_aliasmem;
4765         (*pdb_method)->del_aliasmem = ldapsam_del_aliasmem;
4766         (*pdb_method)->enum_aliasmem = ldapsam_enum_aliasmem;
4767         (*pdb_method)->enum_alias_memberships = ldapsam_alias_memberships;
4768         (*pdb_method)->search_users = ldapsam_search_users;
4769         (*pdb_method)->search_groups = ldapsam_search_groups;
4770         (*pdb_method)->search_aliases = ldapsam_search_aliases;
4771
4772         if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
4773                 (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
4774                 (*pdb_method)->enum_group_memberships =
4775                         ldapsam_enum_group_memberships;
4776                 (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
4777                 (*pdb_method)->sid_to_id = ldapsam_sid_to_id;
4778         }
4779
4780         ldap_state = (*pdb_method)->private_data;
4781         ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
4782
4783         /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
4784         
4785         nt_status = smbldap_search_domain_info(ldap_state->smbldap_state,
4786                                                &result, 
4787                                                ldap_state->domain_name, True);
4788         
4789         if ( !NT_STATUS_IS_OK(nt_status) ) {
4790                 DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain "
4791                           "info, nor add one to the domain\n"));
4792                 DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, "
4793                              "will be unable to allocate new users/groups, "
4794                              "and will risk BDCs having inconsistant SIDs\n"));
4795                 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
4796                 return NT_STATUS_OK;
4797         }
4798
4799         /* Given that the above might fail, everything below this must be
4800          * optional */
4801         
4802         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
4803                                  result);
4804         if (!entry) {
4805                 DEBUG(0, ("pdb_init_ldapsam: Could not get domain info "
4806                           "entry\n"));
4807                 ldap_msgfree(result);
4808                 return NT_STATUS_UNSUCCESSFUL;
4809         }
4810
4811         dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
4812         if (!dn) {
4813                 return NT_STATUS_UNSUCCESSFUL;
4814         }
4815
4816         ldap_state->domain_dn = smb_xstrdup(dn);
4817         ldap_memfree(dn);
4818
4819         if (smbldap_get_single_pstring(
4820                     ldap_state->smbldap_state->ldap_struct,
4821                     entry, 
4822                     get_userattr_key2string(ldap_state->schema_ver,
4823                                             LDAP_ATTR_USER_SID), 
4824                     domain_sid_string)) {
4825                 BOOL found_sid;
4826                 if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
4827                         DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be "
4828                                   "read as a valid SID\n", domain_sid_string));
4829                         return NT_STATUS_INVALID_PARAMETER;
4830                 }
4831                 found_sid = secrets_fetch_domain_sid(ldap_state->domain_name,
4832                                                      &secrets_domain_sid);
4833                 if (!found_sid || !sid_equal(&secrets_domain_sid,
4834                                              &ldap_domain_sid)) {
4835                         fstring new_sid_str, old_sid_str;
4836                         DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain "
4837                                   "%s based on pdb_ldap results %s -> %s\n",
4838                                   ldap_state->domain_name,
4839                                   sid_to_string(old_sid_str,
4840                                                 &secrets_domain_sid),
4841                                   sid_to_string(new_sid_str,
4842                                                 &ldap_domain_sid)));
4843                         
4844                         /* reset secrets.tdb sid */
4845                         secrets_store_domain_sid(ldap_state->domain_name,
4846                                                  &ldap_domain_sid);
4847                         DEBUG(1, ("New global sam SID: %s\n",
4848                                   sid_to_string(new_sid_str,
4849                                                 get_global_sam_sid())));
4850                 }
4851                 sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
4852         }
4853
4854         if (smbldap_get_single_pstring(
4855                     ldap_state->smbldap_state->ldap_struct,
4856                     entry, 
4857                     get_attr_key2string( dominfo_attr_list,
4858                                          LDAP_ATTR_ALGORITHMIC_RID_BASE ),
4859                     alg_rid_base_string)) {
4860                 alg_rid_base = (uint32)atol(alg_rid_base_string);
4861                 if (alg_rid_base != algorithmic_rid_base()) {
4862                         DEBUG(0, ("The value of 'algorithmic RID base' has "
4863                                   "changed since the LDAP\n"
4864                                   "database was initialised.  Aborting. \n"));
4865                         ldap_msgfree(result);
4866                         return NT_STATUS_UNSUCCESSFUL;
4867                 }
4868         }
4869         ldap_msgfree(result);
4870
4871         return NT_STATUS_OK;
4872 }
4873
4874 NTSTATUS pdb_ldap_init(void)
4875 {
4876         NTSTATUS nt_status;
4877         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
4878                 return nt_status;
4879
4880         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
4881                 return nt_status;
4882
4883         /* Let pdb_nds register backends */
4884         pdb_nds_init();
4885
4886         return NT_STATUS_OK;
4887 }