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