24a7304f8739089b9b7b6e1a69be2602cf39d71c
[kai/samba.git] / source3 / passdb / pdb_ldap.c
1 /* 
2    Unix SMB/CIFS implementation.
3    LDAP protocol helper functions for SAMBA
4    Copyright (C) Jean Fran├žois Micouleau        1998
5    Copyright (C) Gerald Carter                  2001-2003
6    Copyright (C) Shahms King                    2001
7    Copyright (C) Andrew Bartlett                2002-2003
8    Copyright (C) Stefan (metze) Metzmacher      2002-2003
9     
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23    
24 */
25
26 /* TODO:
27 *  persistent connections: if using NSS LDAP, many connections are made
28 *      however, using only one within Samba would be nice
29 *  
30 *  Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
31 *
32 *  Other LDAP based login attributes: accountExpires, etc.
33 *  (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
34 *  structures don't have fields for some of these attributes)
35 *
36 *  SSL is done, but can't get the certificate based authentication to work
37 *  against on my test platform (Linux 2.4, OpenLDAP 2.x)
38 */
39
40 /* NOTE: this will NOT work against an Active Directory server
41 *  due to the fact that the two password fields cannot be retrieved
42 *  from a server; recommend using security = domain in this situation
43 *  and/or winbind
44 */
45
46 #include "includes.h"
47
48 #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) {