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