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