e3dedcd06ed237dab341fe763c0f86e25369db9a
[nivanova/samba-autobuild/.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         size_t num_sids, num_gids;
2917         char *gidstr;
2918         gid_t primary_gid = -1;
2919
2920         *pp_sids = NULL;
2921         num_sids = 0;
2922
2923         if (pdb_get_username(user) == NULL) {
2924                 return NT_STATUS_INVALID_PARAMETER;
2925         }
2926
2927         escape_name = escape_ldap_string(talloc_tos(), pdb_get_username(user));
2928         if (escape_name == NULL)
2929                 return NT_STATUS_NO_MEMORY;
2930
2931         if (user->unix_pw) {
2932                 primary_gid = user->unix_pw->pw_gid;
2933         } else {
2934                 /* retrieve the users primary gid */
2935                 filter = talloc_asprintf(mem_ctx,
2936                                          "(&(objectClass=%s)(uid=%s))",
2937                                          LDAP_OBJ_SAMBASAMACCOUNT,
2938                                          escape_name);
2939                 if (filter == NULL) {
2940                         ret = NT_STATUS_NO_MEMORY;
2941                         goto done;
2942                 }
2943
2944                 rc = smbldap_search(conn, lp_ldap_suffix(),
2945                                     LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
2946
2947                 if (rc != LDAP_SUCCESS)
2948                         goto done;
2949
2950                 talloc_autofree_ldapmsg(mem_ctx, result);
2951
2952                 count = ldap_count_entries(priv2ld(ldap_state), result);
2953
2954                 switch (count) {
2955                 case 0:
2956                         DEBUG(1, ("User account [%s] not found!\n", pdb_get_username(user)));
2957                         ret = NT_STATUS_NO_SUCH_USER;
2958                         goto done;
2959                 case 1:
2960                         entry = ldap_first_entry(priv2ld(ldap_state), result);
2961
2962                         gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx);
2963                         if (!gidstr) {
2964                                 DEBUG (1, ("Unable to find the member's gid!\n"));
2965                                 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2966                                 goto done;
2967                         }
2968                         primary_gid = strtoul(gidstr, NULL, 10);
2969                         break;
2970                 default:
2971                         DEBUG(1, ("found more than one account with the same user name ?!\n"));
2972                         ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2973                         goto done;
2974                 }
2975         }
2976
2977         filter = talloc_asprintf(mem_ctx,
2978                                  "(&(objectClass=%s)(|(memberUid=%s)(gidNumber=%u)))",
2979                                  LDAP_OBJ_POSIXGROUP, escape_name, (unsigned int)primary_gid);
2980         if (filter == NULL) {
2981                 ret = NT_STATUS_NO_MEMORY;
2982                 goto done;
2983         }
2984
2985         rc = smbldap_search(conn, lp_ldap_suffix(),
2986                             LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
2987
2988         if (rc != LDAP_SUCCESS)
2989                 goto done;
2990
2991         talloc_autofree_ldapmsg(mem_ctx, result);
2992
2993         num_gids = 0;
2994         *pp_gids = NULL;
2995
2996         num_sids = 0;
2997         *pp_sids = NULL;
2998
2999         /* We need to add the primary group as the first gid/sid */
3000
3001         if (!add_gid_to_array_unique(mem_ctx, primary_gid, pp_gids, &num_gids)) {
3002                 ret = NT_STATUS_NO_MEMORY;
3003                 goto done;
3004         }
3005
3006         /* This sid will be replaced later */
3007
3008         ret = add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids,
3009                                       &num_sids);
3010         if (!NT_STATUS_IS_OK(ret)) {
3011                 goto done;
3012         }
3013
3014         for (entry = ldap_first_entry(conn->ldap_struct, result);
3015              entry != NULL;
3016              entry = ldap_next_entry(conn->ldap_struct, entry))
3017         {
3018                 fstring str;
3019                 struct dom_sid sid;
3020                 gid_t gid;
3021                 char *end;
3022
3023                 if (!smbldap_get_single_attribute(conn->ldap_struct,
3024                                                   entry, "sambaSID",
3025                                                   str, sizeof(str)-1))
3026                         continue;
3027
3028                 if (!string_to_sid(&sid, str))
3029                         goto done;
3030
3031                 if (!smbldap_get_single_attribute(conn->ldap_struct,
3032                                                   entry, "gidNumber",
3033                                                   str, sizeof(str)-1))
3034                         continue;
3035
3036                 gid = strtoul(str, &end, 10);
3037
3038                 if (PTR_DIFF(end, str) != strlen(str))
3039                         goto done;
3040
3041                 if (gid == primary_gid) {
3042                         sid_copy(&(*pp_sids)[0], &sid);
3043                 } else {
3044                         if (!add_gid_to_array_unique(mem_ctx, gid, pp_gids,
3045                                                 &num_gids)) {
3046                                 ret = NT_STATUS_NO_MEMORY;
3047                                 goto done;
3048                         }
3049                         ret = add_sid_to_array_unique(mem_ctx, &sid, pp_sids,
3050                                                       &num_sids);
3051                         if (!NT_STATUS_IS_OK(ret)) {
3052                                 goto done;
3053                         }
3054                 }
3055         }
3056
3057         if (sid_compare(&global_sid_NULL, &(*pp_sids)[0]) == 0) {
3058                 DEBUG(3, ("primary group of [%s] not found\n",
3059                           pdb_get_username(user)));
3060                 goto done;
3061         }
3062
3063         *p_num_groups = num_sids;
3064
3065         ret = NT_STATUS_OK;
3066
3067  done:
3068
3069         TALLOC_FREE(escape_name);
3070         return ret;
3071 }
3072
3073 /**********************************************************************
3074  * Augment a posixGroup object with a sambaGroupMapping domgroup
3075  *********************************************************************/
3076
3077 static NTSTATUS ldapsam_map_posixgroup(TALLOC_CTX *mem_ctx,
3078                                        struct ldapsam_privates *ldap_state,
3079                                        GROUP_MAP *map)
3080 {
3081         const char *filter, *dn;
3082         LDAPMessage *msg, *entry;
3083         LDAPMod **mods;
3084         int rc;
3085
3086         filter = talloc_asprintf(mem_ctx,
3087                                  "(&(objectClass=%s)(gidNumber=%u))",
3088                                  LDAP_OBJ_POSIXGROUP, (unsigned int)map->gid);
3089         if (filter == NULL) {
3090                 return NT_STATUS_NO_MEMORY;
3091         }
3092
3093         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
3094                                    get_attr_list(mem_ctx, groupmap_attr_list),
3095                                    &msg);
3096         talloc_autofree_ldapmsg(mem_ctx, msg);
3097
3098         if ((rc != LDAP_SUCCESS) ||
3099             (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
3100             ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
3101                 return NT_STATUS_NO_SUCH_GROUP;
3102         }
3103
3104         dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
3105         if (dn == NULL) {
3106                 return NT_STATUS_NO_MEMORY;
3107         }
3108
3109         mods = NULL;
3110         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass",
3111                         LDAP_OBJ_GROUPMAP);
3112         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaSid",
3113                          sid_string_talloc(mem_ctx, &map->sid));
3114         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaGroupType",
3115                          talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
3116         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
3117                          map->nt_name);
3118         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
3119                          map->comment);
3120         talloc_autofree_ldapmod(mem_ctx, mods);
3121
3122         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
3123         if (rc != LDAP_SUCCESS) {
3124                 return NT_STATUS_ACCESS_DENIED;
3125         }
3126
3127         return NT_STATUS_OK;
3128 }
3129
3130 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
3131                                                 GROUP_MAP *map)
3132 {
3133         struct ldapsam_privates *ldap_state =
3134                 (struct ldapsam_privates *)methods->private_data;
3135         LDAPMessage *msg = NULL;
3136         LDAPMod **mods = NULL;
3137         const char *attrs[] = { NULL };
3138         char *filter;
3139
3140         char *dn;
3141         TALLOC_CTX *mem_ctx;
3142         NTSTATUS result;
3143
3144         struct dom_sid sid;
3145
3146         int rc;
3147
3148         mem_ctx = talloc_new(NULL);
3149         if (mem_ctx == NULL) {
3150                 DEBUG(0, ("talloc_new failed\n"));
3151                 return NT_STATUS_NO_MEMORY;
3152         }
3153
3154         filter = talloc_asprintf(mem_ctx, "(sambaSid=%s)",
3155                                  sid_string_talloc(mem_ctx, &map->sid));
3156         if (filter == NULL) {
3157                 result = NT_STATUS_NO_MEMORY;
3158                 goto done;
3159         }
3160
3161         rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
3162                             LDAP_SCOPE_SUBTREE, filter, attrs, True, &msg);
3163         talloc_autofree_ldapmsg(mem_ctx, msg);
3164
3165         if ((rc == LDAP_SUCCESS) &&
3166             (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) > 0)) {
3167
3168                 DEBUG(3, ("SID %s already present in LDAP, refusing to add "
3169                           "group mapping entry\n", sid_string_dbg(&map->sid)));
3170                 result = NT_STATUS_GROUP_EXISTS;
3171                 goto done;
3172         }
3173
3174         switch (map->sid_name_use) {
3175
3176         case SID_NAME_DOM_GRP:
3177                 /* To map a domain group we need to have a posix group
3178                    to attach to. */
3179                 result = ldapsam_map_posixgroup(mem_ctx, ldap_state, map);
3180                 goto done;
3181                 break;
3182
3183         case SID_NAME_ALIAS:
3184                 if (!sid_check_is_in_our_domain(&map->sid) 
3185                         && !sid_check_is_in_builtin(&map->sid) ) 
3186                 {
3187                         DEBUG(3, ("Refusing to map sid %s as an alias, not in our domain\n",
3188                                   sid_string_dbg(&map->sid)));
3189                         result = NT_STATUS_INVALID_PARAMETER;
3190                         goto done;
3191                 }
3192                 break;
3193
3194         default:
3195                 DEBUG(3, ("Got invalid use '%s' for mapping\n",
3196                           sid_type_lookup(map->sid_name_use)));
3197                 result = NT_STATUS_INVALID_PARAMETER;
3198                 goto done;
3199         }
3200
3201         /* Domain groups have been mapped in a separate routine, we have to
3202          * create an alias now */
3203
3204         if (map->gid == -1) {
3205                 DEBUG(10, ("Refusing to map gid==-1\n"));
3206                 result = NT_STATUS_INVALID_PARAMETER;
3207                 goto done;
3208         }
3209
3210         if (pdb_gid_to_sid(map->gid, &sid)) {
3211                 DEBUG(3, ("Gid %u is already mapped to SID %s, refusing to "
3212                           "add\n", (unsigned int)map->gid, sid_string_dbg(&sid)));
3213                 result = NT_STATUS_GROUP_EXISTS;
3214                 goto done;
3215         }
3216
3217         /* Ok, enough checks done. It's still racy to go ahead now, but that's
3218          * the best we can get out of LDAP. */
3219
3220         dn = talloc_asprintf(mem_ctx, "sambaSid=%s,%s",
3221                              sid_string_talloc(mem_ctx, &map->sid),
3222                              lp_ldap_group_suffix());
3223         if (dn == NULL) {
3224                 result = NT_STATUS_NO_MEMORY;
3225                 goto done;
3226         }
3227
3228         mods = NULL;
3229
3230         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
3231                          LDAP_OBJ_SID_ENTRY);
3232         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
3233                          LDAP_OBJ_GROUPMAP);
3234         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaSid",
3235                          sid_string_talloc(mem_ctx, &map->sid));
3236         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaGroupType",
3237                          talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
3238         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "displayName",
3239                          map->nt_name);
3240         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "description",
3241                          map->comment);
3242         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "gidNumber",
3243                          talloc_asprintf(mem_ctx, "%u", (unsigned int)map->gid));
3244         talloc_autofree_ldapmod(mem_ctx, mods);
3245
3246         rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
3247
3248         result = (rc == LDAP_SUCCESS) ?
3249                 NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
3250
3251  done:
3252         TALLOC_FREE(mem_ctx);
3253         return result;
3254 }
3255
3256 /**********************************************************************
3257  * Update a group mapping entry. We're quite strict about what can be changed:
3258  * Only the description and displayname may be changed. It simply does not
3259  * make any sense to change the SID, gid or the type in a mapping.
3260  *********************************************************************/
3261
3262 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
3263                                                    GROUP_MAP *map)
3264 {
3265         struct ldapsam_privates *ldap_state =
3266                 (struct ldapsam_privates *)methods->private_data;
3267         int rc;
3268         const char *filter, *dn;
3269         LDAPMessage *msg = NULL;
3270         LDAPMessage *entry = NULL;
3271         LDAPMod **mods = NULL;
3272         TALLOC_CTX *mem_ctx;
3273         NTSTATUS result;
3274
3275         mem_ctx = talloc_new(NULL);
3276         if (mem_ctx == NULL) {
3277                 DEBUG(0, ("talloc_new failed\n"));
3278                 return NT_STATUS_NO_MEMORY;
3279         }
3280
3281         /* Make 100% sure that sid, gid and type are not changed by looking up
3282          * exactly the values we're given in LDAP. */
3283
3284         filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)"
3285                                  "(sambaSid=%s)(gidNumber=%u)"
3286                                  "(sambaGroupType=%d))",
3287                                  LDAP_OBJ_GROUPMAP,
3288                                  sid_string_talloc(mem_ctx, &map->sid),
3289                                  (unsigned int)map->gid, map->sid_name_use);
3290         if (filter == NULL) {
3291                 result = NT_STATUS_NO_MEMORY;
3292                 goto done;
3293         }
3294
3295         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
3296                                    get_attr_list(mem_ctx, groupmap_attr_list),
3297                                    &msg);
3298         talloc_autofree_ldapmsg(mem_ctx, msg);
3299
3300         if ((rc != LDAP_SUCCESS) ||
3301             (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
3302             ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
3303                 result = NT_STATUS_NO_SUCH_GROUP;
3304                 goto done;
3305         }
3306
3307         dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
3308
3309         if (dn == NULL) {
3310                 result = NT_STATUS_NO_MEMORY;
3311                 goto done;
3312         }
3313
3314         mods = NULL;
3315         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
3316                          map->nt_name);
3317         smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
3318                          map->comment);
3319         talloc_autofree_ldapmod(mem_ctx, mods);
3320
3321         if (mods == NULL) {
3322                 DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: "
3323                           "nothing to do\n"));
3324                 result = NT_STATUS_OK;
3325                 goto done;
3326         }
3327
3328         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
3329
3330         if (rc != LDAP_SUCCESS) {
3331                 result = NT_STATUS_ACCESS_DENIED;
3332                 goto done;
3333         }
3334
3335         DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified "
3336                   "group %lu in LDAP\n", (unsigned long)map->gid));
3337
3338         result = NT_STATUS_OK;
3339
3340  done:
3341         TALLOC_FREE(mem_ctx);
3342         return result;
3343 }
3344
3345 /**********************************************************************
3346  *********************************************************************/
3347
3348 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
3349                                                    struct dom_sid sid)
3350 {
3351         struct ldapsam_privates *priv =
3352                 (struct ldapsam_privates *)methods->private_data;
3353         LDAPMessage *msg, *entry;
3354         int rc;
3355         NTSTATUS result;
3356         TALLOC_CTX *mem_ctx;
3357         char *filter;
3358
3359         mem_ctx = talloc_new(NULL);
3360         if (mem_ctx == NULL) {
3361                 DEBUG(0, ("talloc_new failed\n"));
3362                 return NT_STATUS_NO_MEMORY;
3363         }
3364
3365         filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))",
3366                                  LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID,
3367                                  sid_string_talloc(mem_ctx, &sid));
3368         if (filter == NULL) {
3369                 result = NT_STATUS_NO_MEMORY;
3370                 goto done;
3371         }
3372         rc = smbldap_search_suffix(priv->smbldap_state, filter,
3373                                    get_attr_list(mem_ctx, groupmap_attr_list),
3374                                    &msg);
3375         talloc_autofree_ldapmsg(mem_ctx, msg);
3376
3377         if ((rc != LDAP_SUCCESS) ||
3378             (ldap_count_entries(priv2ld(priv), msg) != 1) ||
3379             ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
3380                 result = NT_STATUS_NO_SUCH_GROUP;
3381                 goto done;
3382         }
3383
3384         rc = ldapsam_delete_entry(priv, mem_ctx, entry, LDAP_OBJ_GROUPMAP,
3385                                   get_attr_list(mem_ctx,
3386                                                 groupmap_attr_list_to_delete));
3387
3388         if ((rc == LDAP_NAMING_VIOLATION) ||
3389             (rc == LDAP_NOT_ALLOWED_ON_RDN) ||
3390             (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
3391                 const char *attrs[] = { "sambaGroupType", "description",
3392                                         "displayName", "sambaSIDList",
3393                                         NULL };
3394
3395                 /* Second try. Don't delete the sambaSID attribute, this is
3396                    for "old" entries that are tacked on a winbind
3397                    sambaIdmapEntry. */
3398
3399                 rc = ldapsam_delete_entry(priv, mem_ctx, entry,
3400                                           LDAP_OBJ_GROUPMAP, attrs);
3401         }
3402
3403         if ((rc == LDAP_NAMING_VIOLATION) ||
3404             (rc == LDAP_NOT_ALLOWED_ON_RDN) ||
3405             (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
3406                 const char *attrs[] = { "sambaGroupType", "description",
3407                                         "displayName", "sambaSIDList",
3408                                         "gidNumber", NULL };
3409
3410                 /* Third try. This is a post-3.0.21 alias (containing only
3411                  * sambaSidEntry and sambaGroupMapping classes), we also have
3412                  * to delete the gidNumber attribute, only the sambaSidEntry
3413                  * remains */
3414
3415                 rc = ldapsam_delete_entry(priv, mem_ctx, entry,
3416                                           LDAP_OBJ_GROUPMAP, attrs);
3417         }
3418
3419         result = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3420
3421  done:
3422         TALLOC_FREE(mem_ctx);
3423         return result;
3424  }
3425
3426 /**********************************************************************
3427  *********************************************************************/
3428
3429 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
3430                                     bool update)
3431 {
3432         struct ldapsam_privates *ldap_state =
3433                 (struct ldapsam_privates *)my_methods->private_data;
3434         char *filter = NULL;
3435         int rc;
3436         const char **attr_list;
3437
3438         filter = talloc_asprintf(NULL, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
3439         if (!filter) {
3440                 return NT_STATUS_NO_MEMORY;
3441         }
3442         attr_list = get_attr_list( NULL, groupmap_attr_list );
3443         rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
3444                             LDAP_SCOPE_SUBTREE, filter,
3445                             attr_list, 0, &ldap_state->result);
3446         TALLOC_FREE(attr_list);
3447
3448         if (rc != LDAP_SUCCESS) {
3449                 DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n",
3450                           ldap_err2string(rc)));
3451                 DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n",
3452                           lp_ldap_suffix(), filter));
3453                 ldap_msgfree(ldap_state->result);
3454                 ldap_state->result = NULL;
3455                 TALLOC_FREE(filter);
3456                 return NT_STATUS_UNSUCCESSFUL;
3457         }
3458
3459         TALLOC_FREE(filter);
3460
3461         DEBUG(2, ("ldapsam_setsamgrent: %d entries in the base!\n",
3462                   ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
3463                                      ldap_state->result)));
3464
3465         ldap_state->entry =
3466                 ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
3467                                  ldap_state->result);
3468         ldap_state->index = 0;
3469
3470         return NT_STATUS_OK;
3471 }
3472
3473 /**********************************************************************
3474  *********************************************************************/
3475
3476 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
3477 {
3478         ldapsam_endsampwent(my_methods);
3479 }
3480
3481 /**********************************************************************
3482  *********************************************************************/
3483
3484 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
3485                                     GROUP_MAP *map)
3486 {
3487         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
3488         struct ldapsam_privates *ldap_state =
3489                 (struct ldapsam_privates *)my_methods->private_data;
3490         bool bret = False;
3491
3492         while (!bret) {
3493                 if (!ldap_state->entry)
3494                         return ret;
3495
3496                 ldap_state->index++;
3497                 bret = init_group_from_ldap(ldap_state, map,
3498                                             ldap_state->entry);
3499
3500                 ldap_state->entry =
3501                         ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
3502                                         ldap_state->entry);     
3503         }
3504
3505         return NT_STATUS_OK;
3506 }
3507
3508 /**********************************************************************
3509  *********************************************************************/
3510
3511 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
3512                                            const struct dom_sid *domsid, enum lsa_SidType sid_name_use,
3513                                            GROUP_MAP **pp_rmap,
3514                                            size_t *p_num_entries,
3515                                            bool unix_only)
3516 {
3517         GROUP_MAP map;
3518         size_t entries = 0;
3519
3520         *p_num_entries = 0;
3521         *pp_rmap = NULL;
3522
3523         if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
3524                 DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open "
3525                           "passdb\n"));
3526                 return NT_STATUS_ACCESS_DENIED;
3527         }
3528
3529         while (NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, &map))) {
3530                 if (sid_name_use != SID_NAME_UNKNOWN &&
3531                     sid_name_use != map.sid_name_use) {
3532                         DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
3533                                   "not of the requested type\n", map.nt_name));
3534                         continue;
3535                 }
3536                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
3537                         DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
3538                                   "non mapped\n", map.nt_name));
3539                         continue;
3540                 }
3541
3542                 (*pp_rmap)=SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, entries+1);
3543                 if (!(*pp_rmap)) {
3544                         DEBUG(0,("ldapsam_enum_group_mapping: Unable to "
3545                                  "enlarge group map!\n"));
3546                         return NT_STATUS_UNSUCCESSFUL;
3547                 }
3548
3549                 (*pp_rmap)[entries] = map;
3550
3551                 entries += 1;
3552
3553         }
3554         ldapsam_endsamgrent(methods);
3555
3556         *p_num_entries = entries;
3557
3558         return NT_STATUS_OK;
3559 }
3560
3561 static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
3562                                         const struct dom_sid *alias,
3563                                         const struct dom_sid *member,
3564                                         int modop)
3565 {
3566         struct ldapsam_privates *ldap_state =
3567                 (struct ldapsam_privates *)methods->private_data;
3568         char *dn = NULL;
3569         LDAPMessage *result = NULL;
3570         LDAPMessage *entry = NULL;
3571         int count;
3572         LDAPMod **mods = NULL;
3573         int rc;
3574         enum lsa_SidType type = SID_NAME_USE_NONE;
3575         fstring tmp;
3576
3577         char *filter = NULL;
3578
3579         if (sid_check_is_in_builtin(alias)) {
3580                 type = SID_NAME_ALIAS;
3581         }
3582
3583         if (sid_check_is_in_our_domain(alias)) {
3584                 type = SID_NAME_ALIAS;
3585         }
3586
3587         if (type == SID_NAME_USE_NONE) {
3588                 DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
3589                           sid_string_dbg(alias)));
3590                 return NT_STATUS_NO_SUCH_ALIAS;
3591         }
3592
3593         if (asprintf(&filter,
3594                      "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
3595                      LDAP_OBJ_GROUPMAP, sid_to_fstring(tmp, alias),
3596                      type) < 0) {
3597                 return NT_STATUS_NO_MEMORY;
3598         }
3599
3600         if (ldapsam_search_one_group(ldap_state, filter,
3601                                      &result) != LDAP_SUCCESS) {
3602                 SAFE_FREE(filter);
3603                 return NT_STATUS_NO_SUCH_ALIAS;
3604         }
3605
3606         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
3607                                    result);
3608
3609         if (count < 1) {
3610                 DEBUG(4, ("ldapsam_modify_aliasmem: Did not find alias\n"));
3611                 ldap_msgfree(result);
3612                 SAFE_FREE(filter);
3613                 return NT_STATUS_NO_SUCH_ALIAS;
3614         }
3615
3616         if (count > 1) {
3617                 DEBUG(1, ("ldapsam_modify_aliasmem: Duplicate entries for "
3618                           "filter %s: count=%d\n", filter, count));
3619                 ldap_msgfree(result);
3620                 SAFE_FREE(filter);
3621                 return NT_STATUS_NO_SUCH_ALIAS;
3622         }
3623
3624         SAFE_FREE(filter);
3625
3626         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
3627                                  result);
3628
3629         if (!entry) {
3630                 ldap_msgfree(result);
3631                 return NT_STATUS_UNSUCCESSFUL;
3632         }
3633
3634         dn = smbldap_talloc_dn(talloc_tos(), ldap_state->smbldap_state->ldap_struct, entry);
3635         if (!dn) {
3636                 ldap_msgfree(result);
3637                 return NT_STATUS_UNSUCCESSFUL;
3638         }
3639
3640         smbldap_set_mod(&mods, modop,
3641                         get_attr_key2string(groupmap_attr_list,
3642                                             LDAP_ATTR_SID_LIST),
3643                         sid_to_fstring(tmp, member));
3644
3645         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
3646
3647         ldap_mods_free(mods, True);
3648         ldap_msgfree(result);
3649         TALLOC_FREE(dn);
3650
3651         if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
3652                 return NT_STATUS_MEMBER_IN_ALIAS;
3653         }
3654
3655         if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
3656                 return NT_STATUS_MEMBER_NOT_IN_ALIAS;
3657         }
3658
3659         if (rc != LDAP_SUCCESS) {
3660                 return NT_STATUS_UNSUCCESSFUL;
3661         }
3662
3663         return NT_STATUS_OK;
3664 }
3665
3666 static NTSTATUS ldapsam_add_aliasmem(struct pdb_methods *methods,
3667                                      const struct dom_sid *alias,
3668                                      const struct dom_sid *member)
3669 {
3670         return ldapsam_modify_aliasmem(methods, alias, member, LDAP_MOD_ADD);
3671 }
3672
3673 static NTSTATUS ldapsam_del_aliasmem(struct pdb_methods *methods,
3674                                      const struct dom_sid *alias,
3675                                      const struct dom_sid *member)
3676 {
3677         return ldapsam_modify_aliasmem(methods, alias, member,
3678                                        LDAP_MOD_DELETE);
3679 }
3680
3681 static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
3682                                       const struct dom_sid *alias,
3683                                       TALLOC_CTX *mem_ctx,
3684                                       struct dom_sid **pp_members,
3685                                       size_t *p_num_members)
3686 {
3687         struct ldapsam_privates *ldap_state =
3688                 (struct ldapsam_privates *)methods->private_data;
3689         LDAPMessage *result = NULL;
3690         LDAPMessage *entry = NULL;
3691         int count;
3692         char **values = NULL;
3693         int i;
3694         char *filter = NULL;
3695         size_t num_members = 0;
3696         enum lsa_SidType type = SID_NAME_USE_NONE;
3697         fstring tmp;
3698
3699         *pp_members = NULL;
3700         *p_num_members = 0;
3701
3702         if (sid_check_is_in_builtin(alias)) {
3703                 type = SID_NAME_ALIAS;
3704         }
3705
3706         if (sid_check_is_in_our_domain(alias)) {
3707                 type = SID_NAME_ALIAS;
3708         }
3709
3710         if (type == SID_NAME_USE_NONE) {
3711                 DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
3712                           sid_string_dbg(alias)));
3713                 return NT_STATUS_NO_SUCH_ALIAS;
3714         }
3715
3716         if (asprintf(&filter,
3717                      "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
3718                      LDAP_OBJ_GROUPMAP, sid_to_fstring(tmp, alias),
3719                      type) < 0) {
3720                 return NT_STATUS_NO_MEMORY;
3721         }
3722
3723         if (ldapsam_search_one_group(ldap_state, filter,
3724                                      &result) != LDAP_SUCCESS) {
3725                 SAFE_FREE(filter);
3726                 return NT_STATUS_NO_SUCH_ALIAS;
3727         }
3728
3729         count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
3730                                    result);
3731
3732         if (count < 1) {
3733                 DEBUG(4, ("ldapsam_enum_aliasmem: Did not find alias\n"));
3734                 ldap_msgfree(result);
3735                 SAFE_FREE(filter);
3736                 return NT_STATUS_NO_SUCH_ALIAS;
3737         }
3738
3739         if (count > 1) {
3740                 DEBUG(1, ("ldapsam_enum_aliasmem: Duplicate entries for "
3741                           "filter %s: count=%d\n", filter, count));
3742                 ldap_msgfree(result);
3743                 SAFE_FREE(filter);
3744                 return NT_STATUS_NO_SUCH_ALIAS;
3745         }
3746
3747         SAFE_FREE(filter);
3748
3749         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
3750                                  result);
3751
3752         if (!entry) {
3753                 ldap_msgfree(result);
3754                 return NT_STATUS_UNSUCCESSFUL;
3755         }
3756
3757         values = ldap_get_values(ldap_state->smbldap_state->ldap_struct,
3758                                  entry,
3759                                  get_attr_key2string(groupmap_attr_list,
3760                                                      LDAP_ATTR_SID_LIST));
3761
3762         if (values == NULL) {
3763                 ldap_msgfree(result);
3764                 return NT_STATUS_OK;
3765         }
3766
3767         count = ldap_count_values(values);
3768
3769         for (i=0; i<count; i++) {
3770                 struct dom_sid member;
3771                 NTSTATUS status;
3772
3773                 if (!string_to_sid(&member, values[i]))
3774                         continue;
3775
3776                 status = add_sid_to_array(mem_ctx, &member, pp_members,
3777                                           &num_members);
3778                 if (!NT_STATUS_IS_OK(status)) {
3779                         ldap_value_free(values);
3780                         ldap_msgfree(result);
3781                         return status;
3782                 }
3783         }
3784
3785         *p_num_members = num_members;
3786         ldap_value_free(values);
3787         ldap_msgfree(result);
3788
3789         return NT_STATUS_OK;
3790 }
3791
3792 static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
3793                                           TALLOC_CTX *mem_ctx,
3794                                           const struct dom_sid *domain_sid,
3795                                           const struct dom_sid *members,
3796                                           size_t num_members,
3797                                           uint32_t **pp_alias_rids,
3798                                           size_t *p_num_alias_rids)
3799 {
3800         struct ldapsam_privates *ldap_state =
3801                 (struct ldapsam_privates *)methods->private_data;
3802         LDAP *ldap_struct;
3803
3804         const char *attrs[] = { LDAP_ATTRIBUTE_SID, NULL };
3805
3806         LDAPMessage *result = NULL;
3807         LDAPMessage *entry = NULL;
3808         int i;
3809         int rc;
3810         char *filter;
3811         enum lsa_SidType type = SID_NAME_USE_NONE;
3812         bool is_builtin = false;
3813         bool sid_added = false;
3814
3815         *pp_alias_rids = NULL;
3816         *p_num_alias_rids = 0;
3817
3818         if (sid_check_is_builtin(domain_sid)) {
3819                 is_builtin = true;
3820                 type = SID_NAME_ALIAS;
3821         }
3822
3823         if (sid_check_is_domain(domain_sid)) {
3824                 type = SID_NAME_ALIAS;
3825         }
3826
3827         if (type == SID_NAME_USE_NONE) {
3828                 DEBUG(5, ("SID %s is neither builtin nor domain!\n",
3829                           sid_string_dbg(domain_sid)));
3830                 return NT_STATUS_UNSUCCESSFUL;
3831         }
3832
3833         if (num_members == 0) {
3834                 return NT_STATUS_OK;
3835         }
3836
3837         filter = talloc_asprintf(mem_ctx,
3838                                  "(&(objectclass=%s)(sambaGroupType=%d)(|",
3839                                  LDAP_OBJ_GROUPMAP, type);
3840
3841         for (i=0; i<num_members; i++)
3842                 filter = talloc_asprintf(mem_ctx, "%s(sambaSIDList=%s)",
3843                                          filter,
3844                                          sid_string_talloc(mem_ctx,
3845                                                            &members[i]));
3846
3847         filter = talloc_asprintf(mem_ctx, "%s))", filter);
3848
3849         if (filter == NULL) {
3850                 return NT_STATUS_NO_MEMORY;
3851         }
3852
3853         if (is_builtin &&
3854             ldap_state->search_cache.filter &&
3855             strcmp(ldap_state->search_cache.filter, filter) == 0) {
3856                 filter = talloc_move(filter, &ldap_state->search_cache.filter);
3857                 result = ldap_state->search_cache.result;
3858                 ldap_state->search_cache.result = NULL;
3859         } else {
3860                 rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
3861                                     LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
3862                 if (rc != LDAP_SUCCESS) {
3863                         return NT_STATUS_UNSUCCESSFUL;
3864                 }
3865                 talloc_autofree_ldapmsg(filter, result);
3866         }
3867
3868         ldap_struct = ldap_state->smbldap_state->ldap_struct;
3869
3870         for (entry = ldap_first_entry(ldap_struct, result);
3871              entry != NULL;
3872              entry = ldap_next_entry(ldap_struct, entry))
3873         {
3874                 fstring sid_str;
3875                 struct dom_sid sid;
3876                 uint32_t rid;
3877
3878                 if (!smbldap_get_single_attribute(ldap_struct, entry,
3879                                                   LDAP_ATTRIBUTE_SID,
3880                                                   sid_str,
3881                                                   sizeof(sid_str)-1))
3882                         continue;
3883
3884                 if (!string_to_sid(&sid, sid_str))
3885                         continue;
3886
3887                 if (!sid_peek_check_rid(domain_sid, &sid, &rid))
3888                         continue;
3889
3890                 sid_added = true;
3891
3892                 if (!add_rid_to_array_unique(mem_ctx, rid, pp_alias_rids,
3893                                         p_num_alias_rids)) {
3894                         return NT_STATUS_NO_MEMORY;
3895                 }
3896         }
3897
3898         if (!is_builtin && !sid_added) {
3899                 TALLOC_FREE(ldap_state->search_cache.filter);
3900                 /*
3901                  * Note: result is a talloc child of filter because of the
3902                  * talloc_autofree_ldapmsg() usage
3903                  */
3904                 ldap_state->search_cache.filter = talloc_move(ldap_state, &filter);
3905                 ldap_state->search_cache.result = result;
3906         }
3907
3908         return NT_STATUS_OK;
3909 }
3910
3911 static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
3912                                                    enum pdb_policy_type type,
3913                                                    uint32_t value)
3914 {
3915         NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
3916         int rc;
3917         LDAPMod **mods = NULL;
3918         fstring value_string;
3919         const char *policy_attr = NULL;
3920
3921         struct ldapsam_privates *ldap_state =
3922                 (struct ldapsam_privates *)methods->private_data;
3923
3924         DEBUG(10,("ldapsam_set_account_policy_in_ldap\n"));
3925
3926         if (!ldap_state->domain_dn) {
3927                 return NT_STATUS_INVALID_PARAMETER;
3928         }
3929
3930         policy_attr = get_account_policy_attr(type);
3931         if (policy_attr == NULL) {
3932                 DEBUG(0,("ldapsam_set_account_policy_in_ldap: invalid "
3933                          "policy\n"));
3934                 return ntstatus;
3935         }
3936
3937         slprintf(value_string, sizeof(value_string) - 1, "%i", value);
3938
3939         smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
3940
3941         rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn,
3942                             mods);
3943
3944         ldap_mods_free(mods, True);
3945
3946         if (rc != LDAP_SUCCESS) {
3947                 return ntstatus;
3948         }
3949
3950         if (!cache_account_policy_set(type, value)) {
3951                 DEBUG(0,("ldapsam_set_account_policy_in_ldap: failed to "
3952                          "update local tdb cache\n"));
3953                 return ntstatus;
3954         }
3955
3956         return NT_STATUS_OK;
3957 }
3958
3959 static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods,
3960                                            enum pdb_policy_type type,
3961                                            uint32_t value)
3962 {
3963         return ldapsam_set_account_policy_in_ldap(methods, type,
3964                                                   value);
3965 }
3966
3967 static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods,
3968                                                      enum pdb_policy_type type,
3969                                                      uint32_t *value)
3970 {
3971         NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
3972         LDAPMessage *result = NULL;
3973         LDAPMessage *entry = NULL;
3974         int count;
3975         int rc;
3976         char **vals = NULL;
3977         char *filter;
3978         const char *policy_attr = NULL;
3979
3980         struct ldapsam_privates *ldap_state =
3981                 (struct ldapsam_privates *)methods->private_data;
3982
3983         const char *attrs[2];
3984
3985         DEBUG(10,("ldapsam_get_account_policy_from_ldap\n"));
3986
3987         if (!ldap_state->domain_dn) {
3988                 return NT_STATUS_INVALID_PARAMETER;
3989         }
3990
3991         policy_attr = get_account_policy_attr(type);
3992         if (!policy_attr) {
3993                 DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid "
3994                          "policy index: %d\n", type));
3995                 return ntstatus;
3996         }
3997
3998         attrs[0] = policy_attr;
3999         attrs[1] = NULL;
4000
4001         filter = talloc_asprintf(talloc_tos(), "(objectClass=%s)", LDAP_OBJ_DOMINFO);
4002         if (filter == NULL) {
4003                 return NT_STATUS_NO_MEMORY;
4004         }
4005         rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn,
4006                             LDAP_SCOPE_BASE, filter, attrs, 0,
4007                             &result);
4008         TALLOC_FREE(filter);
4009         if (rc != LDAP_SUCCESS) {
4010                 return ntstatus;
4011         }
4012
4013         count = ldap_count_entries(priv2ld(ldap_state), result);
4014         if (count < 1) {
4015                 goto out;
4016         }
4017
4018         entry = ldap_first_entry(priv2ld(ldap_state), result);
4019         if (entry == NULL) {
4020                 goto out;
4021         }
4022
4023         vals = ldap_get_values(priv2ld(ldap_state), entry, policy_attr);
4024         if (vals == NULL) {
4025                 goto out;
4026         }
4027
4028         *value = (uint32_t)atol(vals[0]);
4029
4030         ntstatus = NT_STATUS_OK;
4031
4032 out:
4033         if (vals)
4034                 ldap_value_free(vals);
4035         ldap_msgfree(result);
4036
4037         return ntstatus;
4038 }
4039
4040 /* wrapper around ldapsam_get_account_policy_from_ldap(), handles tdb as cache 
4041
4042    - if user hasn't decided to use account policies inside LDAP just reuse the
4043      old tdb values
4044
4045    - if there is a valid cache entry, return that
4046    - if there is an LDAP entry, update cache and return 
4047    - otherwise set to default, update cache and return
4048
4049    Guenther
4050 */
4051 static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods,
4052                                            enum pdb_policy_type type,
4053                                            uint32_t *value)
4054 {
4055         NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
4056
4057         if (cache_account_policy_get(type, value)) {
4058                 DEBUG(11,("ldapsam_get_account_policy: got valid value from "
4059                           "cache\n"));
4060                 return NT_STATUS_OK;
4061         }
4062
4063         ntstatus = ldapsam_get_account_policy_from_ldap(methods, type,
4064                                                         value);
4065         if (NT_STATUS_IS_OK(ntstatus)) {
4066                 goto update_cache;
4067         }
4068
4069         DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from "
4070                   "ldap\n"));
4071
4072 #if 0
4073         /* should we automagically migrate old tdb value here ? */
4074         if (account_policy_get(type, value))
4075                 goto update_ldap;
4076
4077         DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying "
4078                   "default\n", type));
4079 #endif
4080
4081         if (!account_policy_get_default(type, value)) {
4082                 return ntstatus;
4083         }
4084
4085 /* update_ldap: */
4086
4087         ntstatus = ldapsam_set_account_policy(methods, type, *value);
4088         if (!NT_STATUS_IS_OK(ntstatus)) {
4089                 return ntstatus;
4090         }
4091
4092  update_cache:
4093
4094         if (!cache_account_policy_set(type, *value)) {
4095                 DEBUG(0,("ldapsam_get_account_policy: failed to update local "
4096                          "tdb as a cache\n"));
4097                 return NT_STATUS_UNSUCCESSFUL;
4098         }
4099
4100         return NT_STATUS_OK;
4101 }
4102
4103 static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
4104                                     const struct dom_sid *domain_sid,
4105                                     int num_rids,
4106                                     uint32_t *rids,
4107                                     const char **names,
4108                                     enum lsa_SidType *attrs)
4109 {
4110         struct ldapsam_privates *ldap_state =
4111                 (struct ldapsam_privates *)methods->private_data;
4112         LDAPMessage *msg = NULL;
4113         LDAPMessage *entry;
4114         char *allsids = NULL;
4115         int i, rc, num_mapped;
4116         NTSTATUS result = NT_STATUS_NO_MEMORY;
4117         TALLOC_CTX *mem_ctx;
4118         LDAP *ld;
4119         bool is_builtin;
4120
4121         mem_ctx = talloc_new(NULL);
4122         if (mem_ctx == NULL) {
4123                 DEBUG(0, ("talloc_new failed\n"));
4124                 goto done;
4125         }
4126
4127         if (!sid_check_is_builtin(domain_sid) &&
4128             !sid_check_is_domain(domain_sid)) {
4129                 result = NT_STATUS_INVALID_PARAMETER;
4130                 goto done;
4131         }
4132
4133         if (num_rids == 0) {
4134                 result = NT_STATUS_NONE_MAPPED;
4135                 goto done;
4136         }
4137
4138         for (i=0; i<num_rids; i++)
4139                 attrs[i] = SID_NAME_UNKNOWN;
4140
4141         allsids = talloc_strdup(mem_ctx, "");
4142         if (allsids == NULL) {
4143                 goto done;
4144         }
4145
4146         for (i=0; i<num_rids; i++) {
4147                 struct dom_sid sid;
4148                 sid_compose(&sid, domain_sid, rids[i]);
4149                 allsids = talloc_asprintf_append_buffer(
4150                         allsids, "(sambaSid=%s)",
4151                         sid_string_talloc(mem_ctx, &sid));
4152                 if (allsids == NULL) {
4153                         goto done;
4154                 }
4155         }
4156
4157         /* First look for users */
4158
4159         {
4160                 char *filter;
4161                 const char *ldap_attrs[] = { "uid", "sambaSid", NULL };
4162
4163                 filter = talloc_asprintf(
4164                         mem_ctx, ("(&(objectClass=%s)(|%s))"),
4165                         LDAP_OBJ_SAMBASAMACCOUNT, allsids);
4166
4167                 if (filter == NULL) {
4168                         goto done;
4169                 }
4170
4171                 rc = smbldap_search(ldap_state->smbldap_state,
4172                                     lp_ldap_user_suffix(),
4173                                     LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
4174                                     &msg);
4175                 talloc_autofree_ldapmsg(mem_ctx, msg);
4176         }
4177
4178         if (rc != LDAP_SUCCESS)
4179                 goto done;
4180
4181         ld = ldap_state->smbldap_state->ldap_struct;
4182         num_mapped = 0;
4183
4184         for (entry = ldap_first_entry(ld, msg);
4185              entry != NULL;
4186              entry = ldap_next_entry(ld, entry)) {
4187                 uint32_t rid;
4188                 int rid_index;
4189                 const char *name;
4190
4191                 if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
4192                                                     &rid)) {
4193                         DEBUG(2, ("Could not find sid from ldap entry\n"));
4194                         continue;
4195                 }
4196
4197                 name = smbldap_talloc_single_attribute(ld, entry, "uid",
4198                                                        names);
4199                 if (name == NULL) {
4200                         DEBUG(2, ("Could not retrieve uid attribute\n"));
4201                         continue;
4202                 }
4203
4204                 for (rid_index = 0; rid_index < num_rids; rid_index++) {
4205                         if (rid == rids[rid_index])
4206                                 break;
4207                 }
4208
4209                 if (rid_index == num_rids) {
4210                         DEBUG(2, ("Got a RID not asked for: %d\n", rid));
4211                         continue;
4212                 }
4213
4214                 attrs[rid_index] = SID_NAME_USER;
4215                 names[rid_index] = name;
4216                 num_mapped += 1;
4217         }
4218
4219         if (num_mapped == num_rids) {
4220                 /* No need to look for groups anymore -- we're done */
4221                 result = NT_STATUS_OK;
4222                 goto done;
4223         }
4224
4225         /* Same game for groups */
4226
4227         {
4228                 char *filter;
4229                 const char *ldap_attrs[] = { "cn", "displayName", "sambaSid",
4230                                              "sambaGroupType", NULL };
4231
4232                 filter = talloc_asprintf(
4233                         mem_ctx, "(&(objectClass=%s)(|%s))",
4234                         LDAP_OBJ_GROUPMAP, allsids);
4235                 if (filter == NULL) {
4236                         goto done;
4237                 }
4238
4239                 rc = smbldap_search(ldap_state->smbldap_state,
4240                                     lp_ldap_suffix(),
4241                                     LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
4242                                     &msg);
4243                 talloc_autofree_ldapmsg(mem_ctx, msg);
4244         }
4245
4246         if (rc != LDAP_SUCCESS)
4247                 goto done;
4248
4249         /* ldap_struct might have changed due to a reconnect */
4250
4251         ld = ldap_state->smbldap_state->ldap_struct;
4252
4253         /* For consistency checks, we already checked we're only domain or builtin */
4254
4255         is_builtin = sid_check_is_builtin(domain_sid);
4256
4257         for (entry = ldap_first_entry(ld, msg);
4258              entry != NULL;
4259              entry = ldap_next_entry(ld, entry))
4260         {
4261                 uint32_t rid;
4262                 int rid_index;
4263                 const char *attr;
4264                 enum lsa_SidType type;
4265                 const char *dn = smbldap_talloc_dn(mem_ctx, ld, entry);
4266
4267                 attr = smbldap_talloc_single_attribute(ld, entry, "sambaGroupType",
4268                                                        mem_ctx);
4269                 if (attr == NULL) {
4270                         DEBUG(2, ("Could not extract type from ldap entry %s\n",
4271                                   dn));
4272                         continue;
4273                 }
4274
4275                 type = (enum lsa_SidType)atol(attr);
4276
4277                 /* Consistency checks */
4278                 if ((is_builtin && (type != SID_NAME_ALIAS)) ||
4279                     (!is_builtin && ((type != SID_NAME_ALIAS) &&
4280                                      (type != SID_NAME_DOM_GRP)))) {
4281                         DEBUG(2, ("Rejecting invalid group mapping entry %s\n", dn));
4282                 }
4283
4284                 if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
4285                                                     &rid)) {
4286                         DEBUG(2, ("Could not find sid from ldap entry %s\n", dn));
4287                         continue;
4288                 }
4289
4290                 attr = smbldap_talloc_single_attribute(ld, entry, "displayName", names);
4291
4292                 if (attr == NULL) {
4293                         DEBUG(10, ("Could not retrieve 'displayName' attribute from %s\n",
4294                                    dn));
4295                         attr = smbldap_talloc_single_attribute(ld, entry, "cn", names);
4296                 }
4297
4298                 if (attr == NULL) {
4299                         DEBUG(2, ("Could not retrieve naming attribute from %s\n",
4300                                   dn));
4301                         continue;
4302                 }
4303
4304                 for (rid_index = 0; rid_index < num_rids; rid_index++) {
4305                         if (rid == rids[rid_index])
4306                                 break;
4307                 }
4308
4309                 if (rid_index == num_rids) {
4310                         DEBUG(2, ("Got a RID not asked for: %d\n", rid));
4311                         continue;
4312                 }
4313
4314                 attrs[rid_index] = type;
4315                 names[rid_index] = attr;
4316                 num_mapped += 1;
4317         }
4318
4319         result = NT_STATUS_NONE_MAPPED;
4320
4321         if (num_mapped > 0)
4322                 result = (num_mapped == num_rids) ?
4323                         NT_STATUS_OK : STATUS_SOME_UNMAPPED;
4324  done:
4325         TALLOC_FREE(mem_ctx);
4326         return result;
4327 }
4328
4329 static char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username)
4330 {
4331         char *filter = NULL;
4332         char *escaped = NULL;
4333         char *result = NULL;
4334
4335         if (asprintf(&filter, "(&%s(objectclass=%s))",
4336                           "(uid=%u)", LDAP_OBJ_SAMBASAMACCOUNT) < 0) {
4337                 goto done;
4338         }
4339
4340         escaped = escape_ldap_string(talloc_tos(), username);
4341         if (escaped == NULL) goto done;
4342
4343         result = talloc_string_sub(mem_ctx, filter, "%u", username);
4344
4345  done:
4346         SAFE_FREE(filter);
4347         TALLOC_FREE(escaped);
4348
4349         return result;
4350 }
4351
4352 static const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...)
4353 {
4354         int i, num = 0;
4355         va_list ap;
4356         const char **result;
4357
4358         va_start(ap, mem_ctx);
4359         while (va_arg(ap, const char *) != NULL)
4360                 num += 1;
4361         va_end(ap);
4362
4363         if ((result = TALLOC_ARRAY(mem_ctx, const char *, num+1)) == NULL) {
4364                 return NULL;
4365         }
4366
4367         va_start(ap, mem_ctx);
4368         for (i=0; i<num; i++) {
4369                 result[i] = talloc_strdup(result, va_arg(ap, const char*));
4370                 if (result[i] == NULL) {
4371                         talloc_free(result);
4372                         va_end(ap);
4373                         return NULL;
4374                 }
4375         }
4376         va_end(ap);
4377
4378         result[num] = NULL;
4379         return result;
4380 }
4381
4382 struct ldap_search_state {
4383         struct smbldap_state *connection;
4384
4385         uint32_t acct_flags;
4386         uint16_t group_type;
4387
4388         const char *base;
4389         int scope;
4390         const char *filter;
4391         const char **attrs;
4392         int attrsonly;
4393         void *pagedresults_cookie;
4394
4395         LDAPMessage *entries, *current_entry;
4396         bool (*ldap2displayentry)(struct ldap_search_state *state,
4397                                   TALLOC_CTX *mem_ctx,
4398                                   LDAP *ld, LDAPMessage *entry,
4399                                   struct samr_displayentry *result);
4400 };
4401
4402 static bool ldapsam_search_firstpage(struct pdb_search *search)
4403 {
4404         struct ldap_search_state *state =
4405                 (struct ldap_search_state *)search->private_data;
4406         LDAP *ld;
4407         int rc = LDAP_OPERATIONS_ERROR;
4408
4409         state->entries = NULL;
4410
4411         if (state->connection->paged_results) {
4412                 rc = smbldap_search_paged(state->connection, state->base,
4413                                           state->scope, state->filter,
4414                                           state->attrs, state->attrsonly,
4415                                           lp_ldap_page_size(), &state->entries,
4416                                           &state->pagedresults_cookie);
4417         }
4418
4419         if ((rc != LDAP_SUCCESS) || (state->entries == NULL)) {
4420
4421                 if (state->entries != NULL) {
4422                         /* Left over from unsuccessful paged attempt */
4423                         ldap_msgfree(state->entries);
4424                         state->entries = NULL;
4425                 }
4426
4427                 rc = smbldap_search(state->connection, state->base,
4428                                     state->scope, state->filter, state->attrs,
4429                                     state->attrsonly, &state->entries);
4430
4431                 if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
4432                         return False;
4433
4434                 /* Ok, the server was lying. It told us it could do paged
4435                  * searches when it could not. */
4436                 state->connection->paged_results = False;
4437         }
4438
4439         ld = state->connection->ldap_struct;
4440         if ( ld == NULL) {
4441                 DEBUG(5, ("Don't have an LDAP connection right after a "
4442                           "search\n"));
4443                 return False;
4444         }
4445         state->current_entry = ldap_first_entry(ld, state->entries);
4446
4447         return True;
4448 }
4449
4450 static bool ldapsam_search_nextpage(struct pdb_search *search)
4451 {
4452         struct ldap_search_state *state =
4453                 (struct ldap_search_state *)search->private_data;
4454         int rc;
4455
4456         if (!state->connection->paged_results) {
4457                 /* There is no next page when there are no paged results */
4458                 return False;
4459         }
4460
4461         rc = smbldap_search_paged(state->connection, state->base,
4462                                   state->scope, state->filter, state->attrs,
4463                                   state->attrsonly, lp_ldap_page_size(),
4464                                   &state->entries,
4465                                   &state->pagedresults_cookie);
4466
4467         if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
4468                 return False;
4469
4470         state->current_entry = ldap_first_entry(state->connection->ldap_struct, state->entries);
4471
4472         if (state->current_entry == NULL) {
4473                 ldap_msgfree(state->entries);
4474                 state->entries = NULL;
4475                 return false;
4476         }
4477
4478         return True;
4479 }
4480
4481 static bool ldapsam_search_next_entry(struct pdb_search *search,
4482                                       struct samr_displayentry *entry)
4483 {
4484         struct ldap_search_state *state =
4485                 (struct ldap_search_state *)search->private_data;
4486         bool result;
4487
4488  retry:
4489         if ((state->entries == NULL) && (state->pagedresults_cookie == NULL))
4490                 return False;
4491
4492         if ((state->entries == NULL) &&
4493             !ldapsam_search_nextpage(search))
4494                     return False;
4495
4496         if (state->current_entry == NULL) {
4497                 return false;
4498         }
4499
4500         result = state->ldap2displayentry(state, search,
4501                                           state->connection->ldap_struct,
4502                                           state->current_entry, entry);
4503
4504         if (!result) {
4505                 char *dn;
4506                 dn = ldap_get_dn(state->connection->ldap_struct, state->current_entry);
4507                 DEBUG(5, ("Skipping entry %s\n", dn != NULL ? dn : "<NULL>"));
4508                 if (dn != NULL) ldap_memfree(dn);
4509         }
4510
4511         state->current_entry = ldap_next_entry(state->connection->ldap_struct, state->current_entry);
4512
4513         if (state->current_entry == NULL) {
4514                 ldap_msgfree(state->entries);
4515                 state->entries = NULL;
4516         }
4517
4518         if (!result) goto retry;
4519
4520         return True;
4521 }
4522
4523 static void ldapsam_search_end(struct pdb_search *search)
4524 {
4525         struct ldap_search_state *state =
4526                 (struct ldap_search_state *)search->private_data;
4527         int rc;
4528
4529         if (state->pagedresults_cookie == NULL)
4530                 return;
4531
4532         if (state->entries != NULL)
4533                 ldap_msgfree(state->entries);
4534
4535         state->entries = NULL;
4536         state->current_entry = NULL;
4537
4538         if (!state->connection->paged_results)
4539                 return;
4540
4541         /* Tell the LDAP server we're not interested in the rest anymore. */
4542
4543         rc = smbldap_search_paged(state->connection, state->base, state->scope,
4544                                   state->filter, state->attrs,
4545                                   state->attrsonly, 0, &state->entries,
4546                                   &state->pagedresults_cookie);
4547
4548         if (rc != LDAP_SUCCESS)
4549                 DEBUG(5, ("Could not end search properly\n"));
4550
4551         return;
4552 }
4553
4554 static bool ldapuser2displayentry(struct ldap_search_state *state,
4555                                   TALLOC_CTX *mem_ctx,
4556                                   LDAP *ld, LDAPMessage *entry,
4557                                   struct samr_displayentry *result)
4558 {
4559         char **vals;
4560         size_t converted_size;
4561         struct dom_sid sid;
4562         uint32_t acct_flags;
4563
4564         vals = ldap_get_values(ld, entry, "sambaAcctFlags");
4565         if ((vals == NULL) || (vals[0] == NULL)) {
4566                 DEBUG(5, ("\"sambaAcctFlags\" not found\n"));
4567                 return False;
4568         }
4569         acct_flags = pdb_decode_acct_ctrl(vals[0]);
4570         ldap_value_free(vals);
4571
4572         if ((state->acct_flags != 0) &&
4573             ((state->acct_flags & acct_flags) == 0))
4574                 return False;           
4575
4576         result->acct_flags = acct_flags;
4577         result->account_name = "";
4578         result->fullname = "";
4579         result->description = "";
4580
4581         vals = ldap_get_values(ld, entry, "uid");
4582         if ((vals == NULL) || (vals[0] == NULL)) {
4583                 DEBUG(5, ("\"uid\" not found\n"));
4584                 return False;
4585         }
4586         if (!pull_utf8_talloc(mem_ctx,
4587                               CONST_DISCARD(char **, &result->account_name),
4588                               vals[0], &converted_size))
4589         {
4590                 DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
4591                          strerror(errno)));
4592         }
4593
4594         ldap_value_free(vals);
4595
4596         vals = ldap_get_values(ld, entry, "displayName");
4597         if ((vals == NULL) || (vals[0] == NULL))
4598                 DEBUG(8, ("\"displayName\" not found\n"));
4599         else if (!pull_utf8_talloc(mem_ctx,
4600                                    CONST_DISCARD(char **, &result->fullname),
4601                                    vals[0], &converted_size))
4602         {
4603                 DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
4604                          strerror(errno)));
4605         }
4606
4607         ldap_value_free(vals);
4608
4609         vals = ldap_get_values(ld, entry, "description");
4610         if ((vals == NULL) || (vals[0] == NULL))
4611                 DEBUG(8, ("\"description\" not found\n"));
4612         else if (!pull_utf8_talloc(mem_ctx,
4613                                    CONST_DISCARD(char **, &result->description),
4614                                    vals[0], &converted_size))
4615         {
4616                 DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
4617                          strerror(errno)));
4618         }
4619
4620         ldap_value_free(vals);
4621
4622         if ((result->account_name == NULL) ||
4623             (result->fullname == NULL) ||
4624             (result->description == NULL)) {
4625                 DEBUG(0, ("talloc failed\n"));
4626                 return False;
4627         }
4628
4629         vals = ldap_get_values(ld, entry, "sambaSid");
4630         if ((vals == NULL) || (vals[0] == NULL)) {
4631                 DEBUG(0, ("\"objectSid\" not found\n"));
4632                 return False;
4633         }
4634
4635         if (!string_to_sid(&sid, vals[0])) {
4636                 DEBUG(0, ("Could not convert %s to SID\n", vals[0]));
4637                 ldap_value_free(vals);
4638                 return False;
4639         }
4640         ldap_value_free(vals);
4641
4642         if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
4643                 DEBUG(0, ("sid %s does not belong to our domain\n",
4644                           sid_string_dbg(&sid)));
4645                 return False;
4646         }
4647
4648         return True;
4649 }
4650
4651
4652 static bool ldapsam_search_users(struct pdb_methods *methods,
4653                                  struct pdb_search *search,
4654                                  uint32_t acct_flags)
4655 {
4656         struct ldapsam_privates *ldap_state =
4657                 (struct ldapsam_privates *)methods->private_data;
4658         struct ldap_search_state *state;
4659
4660         state = talloc(search, struct ldap_search_state);
4661         if (state == NULL) {
4662                 DEBUG(0, ("talloc failed\n"));
4663                 return False;
4664         }
4665
4666         state->connection = ldap_state->smbldap_state;
4667
4668         if ((acct_flags != 0) && ((acct_flags & ACB_NORMAL) != 0))
4669                 state->base = lp_ldap_user_suffix();
4670         else if ((acct_flags != 0) &&
4671                  ((acct_flags & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) != 0))
4672                 state->base = lp_ldap_machine_suffix();
4673         else
4674                 state->base = lp_ldap_suffix();
4675
4676         state->acct_flags = acct_flags;
4677         state->base = talloc_strdup(search, state->base);
4678         state->scope = LDAP_SCOPE_SUBTREE;
4679         state->filter = get_ldap_filter(search, "*");
4680         state->attrs = talloc_attrs(search, "uid", "sambaSid",
4681                                     "displayName", "description",
4682                                     "sambaAcctFlags", NULL);
4683         state->attrsonly = 0;
4684         state->pagedresults_cookie = NULL;
4685         state->entries = NULL;
4686         state->ldap2displayentry = ldapuser2displayentry;
4687
4688         if ((state->filter == NULL) || (state->attrs == NULL)) {
4689                 DEBUG(0, ("talloc failed\n"));
4690                 return False;
4691         }
4692
4693         search->private_data = state;
4694         search->next_entry = ldapsam_search_next_entry;
4695         search->search_end = ldapsam_search_end;
4696
4697         return ldapsam_search_firstpage(search);
4698 }
4699
4700 static bool ldapgroup2displayentry(struct ldap_search_state *state,
4701                                    TALLOC_CTX *mem_ctx,
4702                                    LDAP *ld, LDAPMessage *entry,
4703                                    struct samr_displayentry *result)
4704 {
4705         char **vals;
4706         size_t converted_size;
4707         struct dom_sid sid;
4708         uint16_t group_type;
4709
4710         result->account_name = "";
4711         result->fullname = "";
4712         result->description = "";
4713
4714
4715         vals = ldap_get_values(ld, entry, "sambaGroupType");
4716         if ((vals == NULL) || (vals[0] == NULL)) {
4717                 DEBUG(5, ("\"sambaGroupType\" not found\n"));
4718                 if (vals != NULL) {
4719                         ldap_value_free(vals);
4720                 }
4721                 return False;
4722         }
4723
4724         group_type = atoi(vals[0]);
4725
4726         if ((state->group_type != 0) &&
4727             ((state->group_type != group_type))) {
4728                 ldap_value_free(vals);
4729                 return False;
4730         }
4731
4732         ldap_value_free(vals);
4733
4734         /* display name is the NT group name */
4735
4736         vals = ldap_get_values(ld, entry, "displayName");
4737         if ((vals == NULL) || (vals[0] == NULL)) {
4738                 DEBUG(8, ("\"displayName\" not found\n"));
4739
4740                 /* fallback to the 'cn' attribute */
4741                 vals = ldap_get_values(ld, entry, "cn");
4742                 if ((vals == NULL) || (vals[0] == NULL)) {
4743                         DEBUG(5, ("\"cn\" not found\n"));
4744                         return False;
4745                 }
4746                 if (!pull_utf8_talloc(mem_ctx,
4747                                       CONST_DISCARD(char **,
4748                                                     &result->account_name),
4749                                       vals[0], &converted_size))
4750                 {
4751                         DEBUG(0,("ldapgroup2displayentry: pull_utf8_talloc "
4752                                   "failed: %s", strerror(errno)));
4753                 }
4754         }
4755         else if (!pull_utf8_talloc(mem_ctx,
4756                                    CONST_DISCARD(char **,
4757                                                  &result->account_name),
4758                                    vals[0], &converted_size))
4759         {
4760                 DEBUG(0,("ldapgroup2displayentry: pull_utf8_talloc failed: %s",
4761                           strerror(errno)));
4762         }
4763
4764         ldap_value_free(vals);
4765
4766         vals = ldap_get_values(ld, entry, "description");
4767         if ((vals == NULL) || (vals[0] == NULL))
4768                 DEBUG(8, ("\"description\" not found\n"));
4769         else if (!pull_utf8_talloc(mem_ctx,
4770                                    CONST_DISCARD(char **, &result->description),
4771                                    vals[0], &converted_size))
4772         {
4773                 DEBUG(0,("ldapgroup2displayentry: pull_utf8_talloc failed: %s",
4774                           strerror(errno)));
4775         }
4776         ldap_value_free(vals);
4777
4778         if ((result->account_name == NULL) ||
4779             (result->fullname == NULL) ||
4780             (result->description == NULL)) {
4781                 DEBUG(0, ("talloc failed\n"));
4782                 return False;
4783         }
4784
4785         vals = ldap_get_values(ld, entry, "sambaSid");
4786         if ((vals == NULL) || (vals[0] == NULL)) {
4787                 DEBUG(0, ("\"objectSid\" not found\n"));
4788                 if (vals != NULL) {
4789                         ldap_value_free(vals);
4790                 }
4791                 return False;
4792         }
4793
4794         if (!string_to_sid(&sid, vals[0])) {
4795                 DEBUG(0, ("Could not convert %s to SID\n", vals[0]));
4796                 return False;
4797         }
4798
4799         ldap_value_free(vals);
4800
4801         switch (group_type) {
4802                 case SID_NAME_DOM_GRP:
4803                 case SID_NAME_ALIAS:
4804
4805                         if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid) 
4806                                 && !sid_peek_check_rid(&global_sid_Builtin, &sid, &result->rid)) 
4807                         {
4808                                 DEBUG(0, ("%s is not in our domain\n",
4809                                           sid_string_dbg(&sid)));
4810                                 return False;
4811                         }
4812                         break;
4813
4814                 default:
4815                         DEBUG(0,("unkown group type: %d\n", group_type));
4816                         return False;
4817         }
4818
4819         result->acct_flags = 0;
4820
4821         return True;
4822 }
4823
4824 static bool ldapsam_search_grouptype(struct pdb_methods *methods,
4825                                      struct pdb_search *search,
4826                                      const struct dom_sid *sid,
4827                                      enum lsa_SidType type)
4828 {
4829         struct ldapsam_privates *ldap_state =
4830                 (struct ldapsam_privates *)methods->private_data;
4831         struct ldap_search_state *state;
4832         fstring tmp;
4833
4834         state = talloc(search, struct ldap_search_state);
4835         if (state == NULL) {
4836                 DEBUG(0, ("talloc failed\n"));
4837                 return False;
4838         }
4839
4840         state->connection = ldap_state->smbldap_state;
4841
4842         state->base = talloc_strdup(search, lp_ldap_suffix());
4843         state->connection = ldap_state->smbldap_state;
4844         state->scope = LDAP_SCOPE_SUBTREE;
4845         state->filter = talloc_asprintf(search, "(&(objectclass=%s)"
4846                                         "(sambaGroupType=%d)(sambaSID=%s*))",
4847                                          LDAP_OBJ_GROUPMAP,
4848                                          type, sid_to_fstring(tmp, sid));
4849         state->attrs = talloc_attrs(search, "cn", "sambaSid",
4850                                     "displayName", "description",
4851                                     "sambaGroupType", NULL);
4852         state->attrsonly = 0;
4853         state->pagedresults_cookie = NULL;
4854         state->entries = NULL;
4855         state->group_type = type;
4856         state->ldap2displayentry = ldapgroup2displayentry;
4857
4858         if ((state->filter == NULL) || (state->attrs == NULL)) {
4859                 DEBUG(0, ("talloc failed\n"));
4860                 return False;
4861         }
4862
4863         search->private_data = state;
4864         search->next_entry = ldapsam_search_next_entry;
4865         search->search_end = ldapsam_search_end;
4866
4867         return ldapsam_search_firstpage(search);
4868 }
4869
4870 static bool ldapsam_search_groups(struct pdb_methods *methods,
4871                                   struct pdb_search *search)
4872 {
4873         return ldapsam_search_grouptype(methods, search, get_global_sam_sid(), SID_NAME_DOM_GRP);
4874 }
4875
4876 static bool ldapsam_search_aliases(struct pdb_methods *methods,
4877                                    struct pdb_search *search,
4878                                    const struct dom_sid *sid)
4879 {
4880         return ldapsam_search_grouptype(methods, search, sid, SID_NAME_ALIAS);
4881 }
4882
4883 static uint32_t ldapsam_capabilities(struct pdb_methods *methods)
4884 {
4885         return PDB_CAP_STORE_RIDS;
4886 }
4887
4888 static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
4889                                     uint32_t *rid)
4890 {
4891         struct smbldap_state *smbldap_state = priv->smbldap_state;
4892
4893         LDAPMessage *result = NULL;
4894         LDAPMessage *entry = NULL;
4895         LDAPMod **mods = NULL;
4896         NTSTATUS status;
4897         char *value;
4898         int rc;
4899         uint32_t nextRid = 0;
4900         const char *dn;
4901
4902         TALLOC_CTX *mem_ctx;
4903
4904         mem_ctx = talloc_new(NULL);
4905         if (mem_ctx == NULL) {
4906                 DEBUG(0, ("talloc_new failed\n"));
4907                 return NT_STATUS_NO_MEMORY;
4908         }
4909
4910         status = smbldap_search_domain_info(smbldap_state, &result,
4911                                             get_global_sam_name(), False);
4912         if (!NT_STATUS_IS_OK(status)) {
4913                 DEBUG(3, ("Could not get domain info: %s\n",
4914                           nt_errstr(status)));
4915                 goto done;
4916         }
4917
4918         talloc_autofree_ldapmsg(mem_ctx, result);
4919
4920         entry = ldap_first_entry(priv2ld(priv), result);
4921         if (entry == NULL) {
4922                 DEBUG(0, ("Could not get domain info entry\n"));
4923                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4924                 goto done;
4925         }
4926
4927         /* Find the largest of the three attributes "sambaNextRid",
4928            "sambaNextGroupRid" and "sambaNextUserRid". I gave up on the
4929            concept of differentiating between user and group rids, and will
4930            use only "sambaNextRid" in the future. But for compatibility
4931            reasons I look if others have chosen different strategies -- VL */
4932
4933         value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
4934                                                 "sambaNextRid", mem_ctx);
4935         if (value != NULL) {
4936                 uint32_t tmp = (uint32_t)strtoul(value, NULL, 10);
4937                 nextRid = MAX(nextRid, tmp);
4938         }
4939
4940         value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
4941                                                 "sambaNextUserRid", mem_ctx);
4942         if (value != NULL) {
4943                 uint32_t tmp = (uint32_t)strtoul(value, NULL, 10);
4944                 nextRid = MAX(nextRid, tmp);
4945         }
4946
4947         value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
4948                                                 "sambaNextGroupRid", mem_ctx);
4949         if (value != NULL) {
4950                 uint32_t tmp = (uint32_t)strtoul(value, NULL, 10);
4951                 nextRid = MAX(nextRid, tmp);
4952         }
4953
4954         if (nextRid == 0) {
4955                 nextRid = BASE_RID-1;
4956         }
4957
4958         nextRid += 1;
4959
4960         smbldap_make_mod(priv2ld(priv), entry, &mods, "sambaNextRid",
4961                          talloc_asprintf(mem_ctx, "%d", nextRid));
4962         talloc_autofree_ldapmod(mem_ctx, mods);
4963
4964         if ((dn = smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry)) == NULL) {
4965                 status = NT_STATUS_NO_MEMORY;
4966                 goto done;
4967         }
4968
4969         rc = smbldap_modify(smbldap_state, dn, mods);
4970
4971         /* ACCESS_DENIED is used as a placeholder for "the modify failed,
4972          * please retry" */
4973
4974         status = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
4975
4976  done:
4977         if (NT_STATUS_IS_OK(status)) {
4978                 *rid = nextRid;
4979         }
4980
4981         TALLOC_FREE(mem_ctx);
4982         return status;
4983 }
4984
4985 static NTSTATUS ldapsam_new_rid_internal(struct pdb_methods *methods, uint32_t *rid)
4986 {
4987         int i;
4988
4989         for (i=0; i<10; i++) {
4990                 NTSTATUS result = ldapsam_get_new_rid(
4991                         (struct ldapsam_privates *)methods->private_data, rid);
4992                 if (NT_STATUS_IS_OK(result)) {
4993                         return result;
4994                 }
4995
4996                 if (!NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
4997                         return result;
4998                 }
4999
5000                 /* The ldap update failed (maybe a race condition), retry */
5001         }
5002
5003         /* Tried 10 times, fail. */
5004         return NT_STATUS_ACCESS_DENIED;
5005 }
5006
5007 static bool ldapsam_new_rid(struct pdb_methods *methods, uint32_t *rid)
5008 {
5009         NTSTATUS result = ldapsam_new_rid_internal(methods, rid);
5010         return NT_STATUS_IS_OK(result) ? True : False;
5011 }
5012
5013 static bool ldapsam_sid_to_id(struct pdb_methods *methods,
5014                               const struct dom_sid *sid,
5015                               union unid_t *id, enum lsa_SidType *type)
5016 {
5017         struct ldapsam_privates *priv =
5018                 (struct ldapsam_privates *)methods->private_data;
5019         char *filter;
5020         const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber",
5021                                 NULL };
5022         LDAPMessage *result = NULL;
5023         LDAPMessage *entry = NULL;
5024         bool ret = False;
5025         char *value;
5026         int rc;
5027
5028         TALLOC_CTX *mem_ctx;
5029
5030         mem_ctx = talloc_new(NULL);
5031         if (mem_ctx == NULL) {
5032                 DEBUG(0, ("talloc_new failed\n"));
5033                 return False;
5034         }
5035
5036         filter = talloc_asprintf(mem_ctx,
5037                                  "(&(sambaSid=%s)"
5038                                  "(|(objectClass=%s)(objectClass=%s)))",
5039                                  sid_string_talloc(mem_ctx, sid),
5040                                  LDAP_OBJ_GROUPMAP, LDAP_OBJ_SAMBASAMACCOUNT);
5041         if (filter == NULL) {
5042                 DEBUG(5, ("talloc_asprintf failed\n"));
5043                 goto done;
5044         }
5045
5046         rc = smbldap_search_suffix(priv->smbldap_state, filter,
5047                                    attrs, &result);
5048         if (rc != LDAP_SUCCESS) {
5049                 goto done;
5050         }
5051         talloc_autofree_ldapmsg(mem_ctx, result);
5052
5053         if (ldap_count_entries(priv2ld(priv), result) != 1) {
5054                 DEBUG(10, ("Got %d entries, expected one\n",
5055                            ldap_count_entries(priv2ld(priv), result)));
5056                 goto done;
5057         }
5058
5059         entry = ldap_first_entry(priv2ld(priv), result);
5060
5061         value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
5062                                                 "sambaGroupType", mem_ctx);
5063
5064         if (value != NULL) {
5065                 const char *gid_str;
5066                 /* It's a group */
5067
5068                 gid_str = smbldap_talloc_single_attribute(
5069                         priv2ld(priv), entry, "gidNumber", mem_ctx);
5070                 if (gid_str == NULL) {
5071                         DEBUG(1, ("%s has sambaGroupType but no gidNumber\n",
5072                                   smbldap_talloc_dn(mem_ctx, priv2ld(priv),
5073                                                     entry)));
5074                         goto done;
5075                 }
5076
5077                 id->gid = strtoul(gid_str, NULL, 10);
5078                 *type = (enum lsa_SidType)strtoul(value, NULL, 10);
5079                 store_gid_sid_cache(sid, id->gid);
5080                 idmap_cache_set_sid2gid(sid, id->gid);
5081                 ret = True;
5082                 goto done;
5083         }
5084
5085         /* It must be a user */
5086
5087         value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
5088                                                 "uidNumber", mem_ctx);
5089         if (value == NULL) {
5090                 DEBUG(1, ("Could not find uidNumber in %s\n",
5091                           smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry)));
5092                 goto done;
5093         }
5094
5095         id->uid = strtoul(value, NULL, 10);
5096         *type = SID_NAME_USER;
5097         store_uid_sid_cache(sid, id->uid);
5098         idmap_cache_set_sid2uid(sid, id->uid);
5099
5100         ret = True;
5101  done:
5102         TALLOC_FREE(mem_ctx);
5103         return ret;
5104 }
5105
5106 /**
5107  * Find the SID for a uid.
5108  * This is shortcut is only used if ldapsam:trusted is set to true.
5109  */
5110 static bool ldapsam_uid_to_sid(struct pdb_methods *methods, uid_t uid,
5111                                struct dom_sid *sid)
5112 {
5113         struct ldapsam_privates *priv =
5114                 (struct ldapsam_privates *)methods->private_data;
5115         char *filter;
5116         const char *attrs[] = { "sambaSID", NULL };
5117         LDAPMessage *result = NULL;
5118         LDAPMessage *entry = NULL;
5119         bool ret = false;
5120         char *user_sid_string;
5121         struct dom_sid user_sid;
5122         int rc;
5123         TALLOC_CTX *tmp_ctx = talloc_stackframe();
5124
5125         filter = talloc_asprintf(tmp_ctx,
5126                                  "(&(uidNumber=%u)"
5127                                  "(objectClass=%s)"
5128                                  "(objectClass=%s))",
5129                                  (unsigned int)uid,
5130                                  LDAP_OBJ_POSIXACCOUNT,
5131                                  LDAP_OBJ_SAMBASAMACCOUNT);
5132         if (filter == NULL) {
5133                 DEBUG(3, ("talloc_asprintf failed\n"));
5134                 goto done;
5135         }
5136
5137         rc = smbldap_search_suffix(priv->smbldap_state, filter, attrs, &result);
5138         if (rc != LDAP_SUCCESS) {
5139                 goto done;
5140         }
5141         talloc_autofree_ldapmsg(tmp_ctx, result);
5142
5143         if (ldap_count_entries(priv2ld(priv), result) != 1) {
5144                 DEBUG(3, ("ERROR: Got %d entries for uid %u, expected one\n",
5145                            ldap_count_entries(priv2ld(priv), result),
5146                            (unsigned int)uid));
5147                 goto done;
5148         }
5149
5150         entry = ldap_first_entry(priv2ld(priv), result);
5151
5152         user_sid_string = smbldap_talloc_single_attribute(priv2ld(priv), entry,
5153                                                           "sambaSID", tmp_ctx);
5154         if (user_sid_string == NULL) {
5155                 DEBUG(1, ("Could not find sambaSID in object '%s'\n",
5156                           smbldap_talloc_dn(tmp_ctx, priv2ld(priv), entry)));
5157                 goto done;
5158         }
5159
5160         if (!string_to_sid(&user_sid, user_sid_string)) {
5161                 DEBUG(3, ("Error calling sid_string_talloc for sid '%s'\n",
5162                           user_sid_string));
5163                 goto done;
5164         }
5165
5166         sid_copy(sid, &user_sid);
5167
5168         store_uid_sid_cache(sid, uid);
5169         idmap_cache_set_sid2uid(sid, uid);
5170
5171         ret = true;
5172
5173  done:
5174         TALLOC_FREE(tmp_ctx);
5175         return ret;
5176 }
5177
5178 /**
5179  * Find the SID for a gid.
5180  * This is shortcut is only used if ldapsam:trusted is set to true.
5181  */
5182 static bool ldapsam_gid_to_sid(struct pdb_methods *methods, gid_t gid,
5183                                struct dom_sid *sid)
5184 {
5185         struct ldapsam_privates *priv =
5186                 (struct ldapsam_privates *)methods->private_data;
5187         char *filter;
5188         const char *attrs[] = { "sambaSID", NULL };
5189         LDAPMessage *result = NULL;
5190         LDAPMessage *entry = NULL;
5191         bool ret = false;
5192         char *group_sid_string;
5193         struct dom_sid group_sid;
5194         int rc;
5195         TALLOC_CTX *tmp_ctx = talloc_stackframe();
5196
5197         filter = talloc_asprintf(tmp_ctx,
5198                                  "(&(gidNumber=%u)"
5199                                  "(objectClass=%s))",
5200                                  (unsigned int)gid,
5201                                  LDAP_OBJ_GROUPMAP);
5202         if (filter == NULL) {
5203                 DEBUG(3, ("talloc_asprintf failed\n"));
5204                 goto done;
5205         }
5206
5207         rc = smbldap_search_suffix(priv->smbldap_state, filter, attrs, &result);
5208         if (rc != LDAP_SUCCESS) {
5209                 goto done;
5210         }
5211         talloc_autofree_ldapmsg(tmp_ctx, result);
5212
5213         if (ldap_count_entries(priv2ld(priv), result) != 1) {
5214                 DEBUG(3, ("ERROR: Got %d entries for gid %u, expected one\n",
5215                            ldap_count_entries(priv2ld(priv), result),
5216                            (unsigned int)gid));
5217                 goto done;
5218         }
5219
5220         entry = ldap_first_entry(priv2ld(priv), result);
5221
5222         group_sid_string = smbldap_talloc_single_attribute(priv2ld(priv), entry,
5223                                                           "sambaSID", tmp_ctx);
5224         if (group_sid_string == NULL) {
5225                 DEBUG(1, ("Could not find sambaSID in object '%s'\n",
5226                           smbldap_talloc_dn(tmp_ctx, priv2ld(priv), entry)));
5227                 goto done;
5228         }
5229
5230         if (!string_to_sid(&group_sid, group_sid_string)) {
5231                 DEBUG(3, ("Error calling sid_string_talloc for sid '%s'\n",
5232                           group_sid_string));
5233                 goto done;
5234         }
5235
5236         sid_copy(sid, &group_sid);
5237
5238         store_gid_sid_cache(sid, gid);
5239         idmap_cache_set_sid2gid(sid, gid);
5240
5241         ret = true;
5242
5243  done:
5244         TALLOC_FREE(tmp_ctx);
5245         return ret;
5246 }
5247
5248
5249 /*
5250  * The following functions are called only if
5251  * ldapsam:trusted and ldapsam:editposix are
5252  * set to true
5253  */
5254
5255 /*
5256  * ldapsam_create_user creates a new
5257  * posixAccount and sambaSamAccount object
5258  * in the ldap users subtree
5259  *
5260  * The uid is allocated by winbindd.
5261  */
5262
5263 static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
5264                                     TALLOC_CTX *tmp_ctx, const char *name,
5265                                     uint32_t acb_info, uint32_t *rid)
5266 {
5267         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
5268         LDAPMessage *entry = NULL;
5269         LDAPMessage *result = NULL;
5270         uint32_t num_result;
5271         bool is_machine = False;
5272         bool add_posix = False;
5273         LDAPMod **mods = NULL;
5274         struct samu *user;
5275         char *filter;
5276         char *username;
5277         char *homedir;
5278         char *gidstr;
5279         char *uidstr;
5280         char *shell;
5281         const char *dn = NULL;
5282         struct dom_sid group_sid;
5283         struct dom_sid user_sid;
5284         gid_t gid = -1;
5285         uid_t uid = -1;
5286         NTSTATUS ret;
5287         int rc;
5288
5289         if (((acb_info & ACB_NORMAL) && name[strlen(name)-1] == '$') ||
5290               acb_info & ACB_WSTRUST ||
5291               acb_info & ACB_SVRTRUST ||
5292               acb_info & ACB_DOMTRUST) {
5293                 is_machine = True;
5294         }
5295
5296         username = escape_ldap_string(talloc_tos(), name);
5297         filter = talloc_asprintf(tmp_ctx, "(&(uid=%s)(objectClass=%s))",
5298                                  username, LDAP_OBJ_POSIXACCOUNT);
5299         TALLOC_FREE(username);
5300
5301         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5302         if (rc != LDAP_SUCCESS) {
5303                 DEBUG(0,("ldapsam_create_user: ldap search failed!\n"));
5304                 return NT_STATUS_ACCESS_DENIED;
5305         }
5306         talloc_autofree_ldapmsg(tmp_ctx, result);
5307
5308         num_result = ldap_count_entries(priv2ld(ldap_state), result);
5309
5310         if (num_result > 1) {
5311                 DEBUG (0, ("ldapsam_create_user: More than one user with name [%s] ?!\n", name));
5312                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5313         }
5314
5315         if (num_result == 1) {
5316                 char *tmp;
5317                 /* check if it is just a posix account.
5318                  * or if there is a sid attached to this entry
5319                  */
5320
5321                 entry = ldap_first_entry(priv2ld(ldap_state), result);
5322                 if (!entry) {
5323                         return NT_STATUS_UNSUCCESSFUL;
5324                 }
5325
5326                 tmp = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "sambaSID", tmp_ctx);
5327                 if (tmp) {
5328                         DEBUG (1, ("ldapsam_create_user: The user [%s] already exist!\n", name));
5329                         return NT_STATUS_USER_EXISTS;
5330                 }
5331
5332                 /* it is just a posix account, retrieve the dn for later use */
5333                 dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
5334                 if (!dn) {
5335                         DEBUG(0,("ldapsam_create_user: Out of memory!\n"));
5336                         return NT_STATUS_NO_MEMORY;
5337                 }
5338         }
5339
5340         if (num_result == 0) {
5341                 add_posix = True;
5342         }
5343
5344         /* Create the basic samu structure and generate the mods for the ldap commit */
5345         if (!NT_STATUS_IS_OK((ret = ldapsam_new_rid_internal(my_methods, rid)))) {
5346                 DEBUG(1, ("ldapsam_create_user: Could not allocate a new RID\n"));
5347                 return ret;
5348         }
5349
5350         sid_compose(&user_sid, get_global_sam_sid(), *rid);
5351
5352         user = samu_new(tmp_ctx);
5353         if (!user) {
5354                 DEBUG(1,("ldapsam_create_user: Unable to allocate user struct\n"));
5355                 return NT_STATUS_NO_MEMORY;
5356         }
5357
5358         if (!pdb_set_username(user, name, PDB_SET)) {
5359                 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5360                 return NT_STATUS_UNSUCCESSFUL;
5361         }
5362         if (!pdb_set_domain(user, get_global_sam_name(), PDB_SET)) {
5363                 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5364                 return NT_STATUS_UNSUCCESSFUL;
5365         }
5366         if (is_machine) {
5367                 if (acb_info & ACB_NORMAL) {
5368                         if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_SET)) {
5369                                 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5370                                 return NT_STATUS_UNSUCCESSFUL;
5371                         }
5372                 } else {
5373                         if (!pdb_set_acct_ctrl(user, acb_info, PDB_SET)) {
5374                                 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5375                                 return NT_STATUS_UNSUCCESSFUL;
5376                         }
5377                 }
5378         } else {
5379                 if (!pdb_set_acct_ctrl(user, ACB_NORMAL | ACB_DISABLED, PDB_SET)) {
5380                         DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5381                         return NT_STATUS_UNSUCCESSFUL;
5382                 }
5383         }
5384
5385         if (!pdb_set_user_sid(user, &user_sid, PDB_SET)) {
5386                 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5387                 return NT_STATUS_UNSUCCESSFUL;
5388         }
5389
5390         if (!init_ldap_from_sam(ldap_state, NULL, &mods, user, element_is_set_or_changed)) {
5391                 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5392                 return NT_STATUS_UNSUCCESSFUL;
5393         }
5394
5395         if (ldap_state->schema_ver != SCHEMAVER_SAMBASAMACCOUNT) {
5396                 DEBUG(1,("ldapsam_create_user: Unsupported schema version\n"));
5397         }
5398         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
5399
5400         if (add_posix) {
5401                 char *escape_name;
5402
5403                 DEBUG(3,("ldapsam_create_user: Creating new posix user\n"));
5404
5405                 /* retrieve the Domain Users group gid */
5406                 if (!sid_compose(&group_sid, get_global_sam_sid(), DOMAIN_RID_USERS) ||
5407                     !sid_to_gid(&group_sid, &gid)) {
5408                         DEBUG (0, ("ldapsam_create_user: Unable to get the Domain Users gid: bailing out!\n"));
5409                         return NT_STATUS_INVALID_PRIMARY_GROUP;
5410                 }
5411
5412                 /* lets allocate a new userid for this user */
5413                 if (!winbind_allocate_uid(&uid)) {
5414                         DEBUG (0, ("ldapsam_create_user: Unable to allocate a new user id: bailing out!\n"));
5415                         return NT_STATUS_UNSUCCESSFUL;
5416                 }
5417
5418
5419                 if (is_machine) {
5420                         /* TODO: choose a more appropriate default for machines */
5421                         homedir = talloc_sub_specified(tmp_ctx, lp_template_homedir(), "SMB_workstations_home", ldap_state->domain_name, uid, gid);
5422                         shell = talloc_strdup(tmp_ctx, "/bin/false");
5423                 } else {
5424                         homedir = talloc_sub_specified(tmp_ctx, lp_template_homedir(), name, ldap_state->domain_name, uid, gid);
5425                         shell = talloc_sub_specified(tmp_ctx, lp_template_shell(), name, ldap_state->domain_name, uid, gid);
5426                 }
5427                 uidstr = talloc_asprintf(tmp_ctx, "%u", (unsigned int)uid);
5428                 gidstr = talloc_asprintf(tmp_ctx, "%u", (unsigned int)gid);
5429
5430                 escape_name = escape_rdn_val_string_alloc(name);
5431                 if (!escape_name) {
5432                         DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
5433                         return NT_STATUS_NO_MEMORY;
5434                 }
5435
5436                 if (is_machine) {
5437                         dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", escape_name, lp_ldap_machine_suffix ());
5438                 } else {
5439                         dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", escape_name, lp_ldap_user_suffix ());
5440                 }
5441
5442                 SAFE_FREE(escape_name);
5443
5444                 if (!homedir || !shell || !uidstr || !gidstr || !dn) {
5445                         DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
5446                         return NT_STATUS_NO_MEMORY;
5447                 }
5448
5449                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
5450                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
5451                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
5452                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
5453                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
5454                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", homedir);
5455                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", shell);
5456         }
5457
5458         talloc_autofree_ldapmod(tmp_ctx, mods);
5459
5460         if (add_posix) {        
5461                 rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
5462         } else {
5463                 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
5464         }       
5465
5466         if (rc != LDAP_SUCCESS) {
5467                 DEBUG(0,("ldapsam_create_user: failed to create a new user [%s] (dn = %s)\n", name ,dn));
5468                 return NT_STATUS_UNSUCCESSFUL;
5469         }
5470
5471         DEBUG(2,("ldapsam_create_user: added account [%s] in the LDAP database\n", name));
5472
5473         flush_pwnam_cache();
5474
5475         return NT_STATUS_OK;
5476 }
5477
5478 static NTSTATUS ldapsam_delete_user(struct pdb_methods *my_methods, TALLOC_CTX *tmp_ctx, struct samu *sam_acct)
5479 {
5480         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
5481         LDAPMessage *result = NULL;
5482         LDAPMessage *entry = NULL;
5483         int num_result;
5484         const char *dn;
5485         char *filter;
5486         int rc;
5487
5488         DEBUG(0,("ldapsam_delete_user: Attempt to delete user [%s]\n", pdb_get_username(sam_acct)));
5489
5490         filter = talloc_asprintf(tmp_ctx,
5491                                  "(&(uid=%s)"
5492                                  "(objectClass=%s)"
5493                                  "(objectClass=%s))",
5494                                  pdb_get_username(sam_acct),
5495                                  LDAP_OBJ_POSIXACCOUNT,
5496                                  LDAP_OBJ_SAMBASAMACCOUNT);
5497         if (filter == NULL) {
5498                 return NT_STATUS_NO_MEMORY;
5499         }
5500
5501         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5502         if (rc != LDAP_SUCCESS) {
5503                 DEBUG(0,("ldapsam_delete_user: user search failed!\n"));
5504                 return NT_STATUS_UNSUCCESSFUL;
5505         }
5506         talloc_autofree_ldapmsg(tmp_ctx, result);
5507
5508         num_result = ldap_count_entries(priv2ld(ldap_state), result);
5509
5510         if (num_result == 0) {
5511                 DEBUG(0,("ldapsam_delete_user: user not found!\n"));
5512                 return NT_STATUS_NO_SUCH_USER;
5513         }
5514
5515         if (num_result > 1) {
5516                 DEBUG (0, ("ldapsam_delete_user: More than one user with name [%s] ?!\n", pdb_get_username(sam_acct)));
5517                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5518         }
5519
5520         entry = ldap_first_entry(priv2ld(ldap_state), result);
5521         if (!entry) {
5522                 return NT_STATUS_UNSUCCESSFUL;
5523         }
5524
5525         /* it is just a posix account, retrieve the dn for later use */
5526         dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
5527         if (!dn) {
5528                 DEBUG(0,("ldapsam_delete_user: Out of memory!\n"));
5529                 return NT_STATUS_NO_MEMORY;
5530         }
5531
5532         /* try to remove memberships first */
5533         {
5534                 NTSTATUS status;
5535                 struct dom_sid *sids = NULL;
5536                 gid_t *gids = NULL;
5537                 size_t num_groups = 0;
5538                 int i;
5539                 uint32_t user_rid = pdb_get_user_rid(sam_acct);
5540
5541                 status = ldapsam_enum_group_memberships(my_methods,
5542                                                         tmp_ctx,
5543                                                         sam_acct,
5544                                                         &sids,
5545                                                         &gids,
5546                                                         &num_groups);
5547                 if (!NT_STATUS_IS_OK(status)) {
5548                         goto delete_dn;
5549                 }
5550
5551                 for (i=0; i < num_groups; i++) {
5552
5553                         uint32_t group_rid;
5554
5555                         sid_peek_rid(&sids[i], &group_rid);
5556
5557                         ldapsam_del_groupmem(my_methods,
5558                                              tmp_ctx,
5559                                              group_rid,
5560                                              user_rid);
5561                 }
5562         }
5563
5564  delete_dn:
5565
5566         rc = smbldap_delete(ldap_state->smbldap_state, dn);
5567         if (rc != LDAP_SUCCESS) {
5568                 return NT_STATUS_UNSUCCESSFUL;
5569         }
5570
5571         flush_pwnam_cache();
5572
5573         return NT_STATUS_OK;
5574 }
5575
5576 /*
5577  * ldapsam_create_group creates a new
5578  * posixGroup and sambaGroupMapping object
5579  * in the ldap groups subtree
5580  *
5581  * The gid is allocated by winbindd.
5582  */
5583
5584 static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
5585                                          TALLOC_CTX *tmp_ctx,
5586                                          const char *name,
5587                                          uint32_t *rid)
5588 {
5589         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
5590         NTSTATUS ret;
5591         LDAPMessage *entry = NULL;
5592         LDAPMessage *result = NULL;
5593         uint32_t num_result;
5594         bool is_new_entry = False;
5595         LDAPMod **mods = NULL;
5596         char *filter;
5597         char *groupsidstr;
5598         char *groupname;
5599         char *grouptype;
5600         char *gidstr;
5601         const char *dn = NULL;
5602         struct dom_sid group_sid;
5603         gid_t gid = -1;
5604         int rc;
5605
5606         groupname = escape_ldap_string(talloc_tos(), name);
5607         filter = talloc_asprintf(tmp_ctx, "(&(cn=%s)(objectClass=%s))",
5608                                  groupname, LDAP_OBJ_POSIXGROUP);
5609         TALLOC_FREE(groupname);
5610
5611         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5612         if (rc != LDAP_SUCCESS) {
5613                 DEBUG(0,("ldapsam_create_group: ldap search failed!\n"));
5614                 return NT_STATUS_UNSUCCESSFUL;
5615         }
5616         talloc_autofree_ldapmsg(tmp_ctx, result);
5617
5618         num_result = ldap_count_entries(priv2ld(ldap_state), result);
5619
5620         if (num_result > 1) {
5621                 DEBUG (0, ("ldapsam_create_group: There exists more than one group with name [%s]: bailing out!\n", name));
5622                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5623         }
5624
5625         if (num_result == 1) {
5626                 char *tmp;
5627                 /* check if it is just a posix group.
5628                  * or if there is a sid attached to this entry
5629                  */
5630
5631                 entry = ldap_first_entry(priv2ld(ldap_state), result);
5632                 if (!entry) {
5633                         return NT_STATUS_UNSUCCESSFUL;
5634                 }
5635
5636                 tmp = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "sambaSID", tmp_ctx);
5637                 if (tmp) {
5638                         DEBUG (1, ("ldapsam_create_group: The group [%s] already exist!\n", name));
5639                         return NT_STATUS_GROUP_EXISTS;
5640                 }
5641
5642                 /* it is just a posix group, retrieve the gid and the dn for later use */
5643                 tmp = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
5644                 if (!tmp) {
5645                         DEBUG (1, ("ldapsam_create_group: Couldn't retrieve the gidNumber for [%s]?!?!\n", name));
5646                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
5647                 }
5648
5649                 gid = strtoul(tmp, NULL, 10);
5650
5651                 dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
5652                 if (!dn) {
5653                         DEBUG(0,("ldapsam_create_group: Out of memory!\n"));
5654                         return NT_STATUS_NO_MEMORY;
5655                 }
5656         }
5657
5658         if (num_result == 0) {
5659                 is_new_entry = true;
5660         }
5661
5662         if (!NT_STATUS_IS_OK((ret = ldapsam_new_rid_internal(my_methods, rid)))) {
5663                 DEBUG(1, ("ldapsam_create_group: Could not allocate a new RID\n"));
5664                 return ret;
5665         }
5666
5667         sid_compose(&group_sid, get_global_sam_sid(), *rid);
5668
5669         groupsidstr = talloc_strdup(tmp_ctx, sid_string_talloc(tmp_ctx,
5670                                                                &group_sid));
5671         grouptype = talloc_asprintf(tmp_ctx, "%d", SID_NAME_DOM_GRP);
5672
5673         if (!groupsidstr || !grouptype) {
5674                 DEBUG(0,("ldapsam_create_group: Out of memory!\n"));
5675                 return NT_STATUS_NO_MEMORY;
5676         }
5677
5678         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
5679         smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", groupsidstr);
5680         smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", grouptype);
5681         smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", name);
5682
5683         if (is_new_entry) {
5684                 char *escape_name;
5685
5686                 DEBUG(3,("ldapsam_create_user: Creating new posix group\n"));
5687
5688                 /* lets allocate a new groupid for this group */
5689                 if (!winbind_allocate_gid(&gid)) {
5690                         DEBUG (0, ("ldapsam_create_group: Unable to allocate a new group id: bailing out!\n"));
5691                         return NT_STATUS_UNSUCCESSFUL;
5692                 }
5693
5694                 gidstr = talloc_asprintf(tmp_ctx, "%u", (unsigned int)gid);
5695
5696                 escape_name = escape_rdn_val_string_alloc(name);
5697                 if (!escape_name) {
5698                         DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
5699                         return NT_STATUS_NO_MEMORY;
5700                 }
5701
5702                 dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", escape_name, lp_ldap_group_suffix());
5703
5704                 SAFE_FREE(escape_name);
5705
5706                 if (!gidstr || !dn) {
5707                         DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
5708                         return NT_STATUS_NO_MEMORY;
5709                 }
5710
5711                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
5712                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
5713                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
5714         }
5715
5716         talloc_autofree_ldapmod(tmp_ctx, mods);
5717
5718         if (is_new_entry) {     
5719                 rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
5720 #if 0
5721                 if (rc == LDAP_OBJECT_CLASS_VIOLATION) {
5722                         /* This call may fail with rfc2307bis schema */
5723                         /* Retry adding a structural class */
5724                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", "????");
5725                         rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
5726                 }
5727 #endif
5728         } else {
5729                 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
5730         }       
5731
5732         if (rc != LDAP_SUCCESS) {
5733                 DEBUG(0,("ldapsam_create_group: failed to create a new group [%s] (dn = %s)\n", name ,dn));
5734                 return NT_STATUS_UNSUCCESSFUL;
5735         }
5736
5737         DEBUG(2,("ldapsam_create_group: added group [%s] in the LDAP database\n", name));
5738
5739         return NT_STATUS_OK;
5740 }
5741
5742 static NTSTATUS ldapsam_delete_dom_group(struct pdb_methods *my_methods, TALLOC_CTX *tmp_ctx, uint32_t rid)
5743 {
5744         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
5745         LDAPMessage *result = NULL;
5746         LDAPMessage *entry = NULL;
5747         int num_result;
5748         const char *dn;
5749         char *gidstr;
5750         char *filter;
5751         struct dom_sid group_sid;
5752         int rc;
5753
5754         /* get the group sid */
5755         sid_compose(&group_sid, get_global_sam_sid(), rid);
5756
5757         filter = talloc_asprintf(tmp_ctx,
5758                                  "(&(sambaSID=%s)"
5759                                  "(objectClass=%s)"
5760                                  "(objectClass=%s))",
5761                                  sid_string_talloc(tmp_ctx, &group_sid),
5762                                  LDAP_OBJ_POSIXGROUP,
5763                                  LDAP_OBJ_GROUPMAP);
5764         if (filter == NULL) {
5765                 return NT_STATUS_NO_MEMORY;
5766         }
5767
5768         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5769         if (rc != LDAP_SUCCESS) {
5770                 DEBUG(1,("ldapsam_delete_dom_group: group search failed!\n"));
5771                 return NT_STATUS_UNSUCCESSFUL;
5772         }
5773         talloc_autofree_ldapmsg(tmp_ctx, result);
5774
5775         num_result = ldap_count_entries(priv2ld(ldap_state), result);
5776
5777         if (num_result == 0) {
5778                 DEBUG(1,("ldapsam_delete_dom_group: group not found!\n"));
5779                 return NT_STATUS_NO_SUCH_GROUP;
5780         }
5781
5782         if (num_result > 1) {
5783                 DEBUG (0, ("ldapsam_delete_dom_group: More than one group with the same SID ?!\n"));
5784                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5785         }
5786
5787         entry = ldap_first_entry(priv2ld(ldap_state), result);
5788         if (!entry) {
5789                 return NT_STATUS_UNSUCCESSFUL;
5790         }
5791
5792         /* here it is, retrieve the dn for later use */
5793         dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
5794         if (!dn) {
5795                 DEBUG(0,("ldapsam_delete_dom_group: Out of memory!\n"));
5796                 return NT_STATUS_NO_MEMORY;
5797         }
5798
5799         gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
5800         if (!gidstr) {
5801                 DEBUG (0, ("ldapsam_delete_dom_group: Unable to find the group's gid!\n"));
5802                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5803         }
5804
5805         /* check no user have this group marked as primary group */
5806         filter = talloc_asprintf(tmp_ctx,
5807                                  "(&(gidNumber=%s)"
5808                                  "(objectClass=%s)"
5809                                  "(objectClass=%s))",
5810                                  gidstr,
5811                                  LDAP_OBJ_POSIXACCOUNT,
5812                                  LDAP_OBJ_SAMBASAMACCOUNT);
5813
5814         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5815         if (rc != LDAP_SUCCESS) {
5816                 DEBUG(1,("ldapsam_delete_dom_group: accounts search failed!\n"));
5817                 return NT_STATUS_UNSUCCESSFUL;
5818         }
5819         talloc_autofree_ldapmsg(tmp_ctx, result);
5820
5821         num_result = ldap_count_entries(priv2ld(ldap_state), result);
5822
5823         if (num_result != 0) {
5824                 DEBUG(3,("ldapsam_delete_dom_group: Can't delete group, it is a primary group for %d users\n", num_result));
5825                 return NT_STATUS_MEMBERS_PRIMARY_GROUP;
5826         }
5827
5828         rc = smbldap_delete(ldap_state->smbldap_state, dn);
5829         if (rc != LDAP_SUCCESS) {
5830                 return NT_STATUS_UNSUCCESSFUL;
5831         }
5832
5833         return NT_STATUS_OK;
5834 }
5835
5836 static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
5837                                         TALLOC_CTX *tmp_ctx,
5838                                         uint32_t group_rid,
5839                                         uint32_t member_rid,
5840                                         int modop)
5841 {
5842         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
5843         LDAPMessage *entry = NULL;
5844         LDAPMessage *result = NULL;
5845         uint32_t num_result;
5846         LDAPMod **mods = NULL;
5847         char *filter;
5848         char *uidstr;
5849         const char *dn = NULL;
5850         struct dom_sid group_sid;
5851         struct dom_sid member_sid;
5852         int rc;
5853
5854         switch (modop) {
5855         case LDAP_MOD_ADD:
5856                 DEBUG(1,("ldapsam_change_groupmem: add new member(rid=%d) to a domain group(rid=%d)", member_rid, group_rid));
5857                 break;
5858         case LDAP_MOD_DELETE:
5859                 DEBUG(1,("ldapsam_change_groupmem: delete member(rid=%d) from a domain group(rid=%d)", member_rid, group_rid));
5860                 break;
5861         default:
5862                 return NT_STATUS_UNSUCCESSFUL;
5863         }
5864
5865         /* get member sid  */
5866         sid_compose(&member_sid, get_global_sam_sid(), member_rid);
5867
5868         /* get the group sid */
5869         sid_compose(&group_sid, get_global_sam_sid(), group_rid);
5870
5871         filter = talloc_asprintf(tmp_ctx,
5872                                  "(&(sambaSID=%s)"
5873                                  "(objectClass=%s)"
5874                                  "(objectClass=%s))",
5875                                  sid_string_talloc(tmp_ctx, &member_sid),
5876                                  LDAP_OBJ_POSIXACCOUNT,
5877                                  LDAP_OBJ_SAMBASAMACCOUNT);
5878         if (filter == NULL) {
5879                 return NT_STATUS_NO_MEMORY;
5880         }
5881
5882         /* get the member uid */
5883         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5884         if (rc != LDAP_SUCCESS) {
5885                 DEBUG(1,("ldapsam_change_groupmem: member search failed!\n"));
5886                 return NT_STATUS_UNSUCCESSFUL;
5887         }
5888         talloc_autofree_ldapmsg(tmp_ctx, result);
5889
5890         num_result = ldap_count_entries(priv2ld(ldap_state), result);
5891
5892         if (num_result == 0) {
5893                 DEBUG(1,("ldapsam_change_groupmem: member not found!\n"));
5894                 return NT_STATUS_NO_SUCH_MEMBER;
5895         }
5896
5897         if (num_result > 1) {
5898                 DEBUG (0, ("ldapsam_change_groupmem: More than one account with the same SID ?!\n"));
5899                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5900         }
5901
5902         entry = ldap_first_entry(priv2ld(ldap_state), result);
5903         if (!entry) {
5904                 return NT_STATUS_UNSUCCESSFUL;
5905         }
5906
5907         if (modop == LDAP_MOD_DELETE) {
5908                 /* check if we are trying to remove the member from his primary group */
5909                 char *gidstr;
5910                 gid_t user_gid, group_gid;
5911
5912                 gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
5913                 if (!gidstr) {
5914                         DEBUG (0, ("ldapsam_change_groupmem: Unable to find the member's gid!\n"));
5915                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
5916                 }
5917
5918                 user_gid = strtoul(gidstr, NULL, 10);
5919
5920                 if (!sid_to_gid(&group_sid, &group_gid)) {
5921                         DEBUG (0, ("ldapsam_change_groupmem: Unable to get group gid from SID!\n"));
5922                         return NT_STATUS_UNSUCCESSFUL;
5923                 }
5924
5925                 if (user_gid == group_gid) {
5926                         DEBUG (3, ("ldapsam_change_groupmem: can't remove user from its own primary group!\n"));
5927                         return NT_STATUS_MEMBERS_PRIMARY_GROUP;
5928                 }
5929         }
5930
5931         /* here it is, retrieve the uid for later use */
5932         uidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "uid", tmp_ctx);
5933         if (!uidstr) {
5934                 DEBUG (0, ("ldapsam_change_groupmem: Unable to find the member's name!\n"));
5935                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5936         }
5937
5938         filter = talloc_asprintf(tmp_ctx,
5939                                  "(&(sambaSID=%s)"
5940                                  "(objectClass=%s)"
5941                                  "(objectClass=%s))",
5942                                  sid_string_talloc(tmp_ctx, &group_sid),
5943                                  LDAP_OBJ_POSIXGROUP,
5944                                  LDAP_OBJ_GROUPMAP);
5945
5946         /* get the group */
5947         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5948         if (rc != LDAP_SUCCESS) {
5949                 DEBUG(1,("ldapsam_change_groupmem: group search failed!\n"));
5950                 return NT_STATUS_UNSUCCESSFUL;
5951         }
5952         talloc_autofree_ldapmsg(tmp_ctx, result);
5953
5954         num_result = ldap_count_entries(priv2ld(ldap_state), result);
5955
5956         if (num_result == 0) {
5957                 DEBUG(1,("ldapsam_change_groupmem: group not found!\n"));
5958                 return NT_STATUS_NO_SUCH_GROUP;
5959         }
5960
5961         if (num_result > 1) {
5962                 DEBUG (0, ("ldapsam_change_groupmem: More than one group with the same SID ?!\n"));
5963                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5964         }
5965
5966         entry = ldap_first_entry(priv2ld(ldap_state), result);
5967         if (!entry) {
5968                 return NT_STATUS_UNSUCCESSFUL;
5969         }
5970
5971         /* here it is, retrieve the dn for later use */
5972         dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
5973         if (!dn) {
5974                 DEBUG(0,("ldapsam_change_groupmem: Out of memory!\n"));
5975                 return NT_STATUS_NO_MEMORY;
5976         }
5977
5978         smbldap_set_mod(&mods, modop, "memberUid", uidstr);
5979
5980         talloc_autofree_ldapmod(tmp_ctx, mods);
5981
5982         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
5983         if (rc != LDAP_SUCCESS) {
5984                 if (rc == LDAP_TYPE_OR_VALUE_EXISTS && modop == LDAP_MOD_ADD) {
5985                         DEBUG(1,("ldapsam_change_groupmem: member is already in group, add failed!\n"));
5986                         return NT_STATUS_MEMBER_IN_GROUP;
5987                 }
5988                 if (rc == LDAP_NO_SUCH_ATTRIBUTE && modop == LDAP_MOD_DELETE) {
5989                         DEBUG(1,("ldapsam_change_groupmem: member is not in group, delete failed!\n"));
5990                         return NT_STATUS_MEMBER_NOT_IN_GROUP;
5991                 }
5992                 return NT_STATUS_UNSUCCESSFUL;
5993         }
5994
5995         return NT_STATUS_OK;
5996 }
5997
5998 static NTSTATUS ldapsam_add_groupmem(struct pdb_methods *my_methods,
5999                                      TALLOC_CTX *tmp_ctx,
6000                                      uint32_t group_rid,
6001                                      uint32_t member_rid)
6002 {
6003         return ldapsam_change_groupmem(my_methods, tmp_ctx, group_rid, member_rid, LDAP_MOD_ADD);
6004 }
6005 static NTSTATUS ldapsam_del_groupmem(struct pdb_methods *my_methods,
6006                                      TALLOC_CTX *tmp_ctx,
6007                                      uint32_t group_rid,
6008                                      uint32_t member_rid)
6009 {
6010         return ldapsam_change_groupmem(my_methods, tmp_ctx, group_rid, member_rid, LDAP_MOD_DELETE);
6011 }
6012
6013 static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
6014                                           TALLOC_CTX *mem_ctx,
6015                                           struct samu *sampass)
6016 {
6017         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
6018         LDAPMessage *entry = NULL;
6019         LDAPMessage *result = NULL;
6020         uint32_t num_result;
6021         LDAPMod **mods = NULL;
6022         char *filter;
6023         char *escape_username;
6024         char *gidstr;
6025         const char *dn = NULL;
6026         gid_t gid;
6027         int rc;
6028
6029         DEBUG(0,("ldapsam_set_primary_group: Attempt to set primary group for user [%s]\n", pdb_get_username(sampass)));
6030
6031         if (!sid_to_gid(pdb_get_group_sid(sampass), &gid)) {
6032                 DEBUG(0,("ldapsam_set_primary_group: failed to retrieve gid from user's group SID!\n"));
6033                 return NT_STATUS_UNSUCCESSFUL;
6034         }
6035         gidstr = talloc_asprintf(mem_ctx, "%u", (unsigned int)gid);
6036         if (!gidstr) {
6037                 DEBUG(0,("ldapsam_set_primary_group: Out of Memory!\n"));
6038                 return NT_STATUS_NO_MEMORY;
6039         }
6040
6041         escape_username = escape_ldap_string(talloc_tos(),
6042                                              pdb_get_username(sampass));
6043         if (escape_username== NULL) {
6044                 return NT_STATUS_NO_MEMORY;
6045         }
6046
6047         filter = talloc_asprintf(mem_ctx,
6048                                  "(&(uid=%s)"
6049                                  "(objectClass=%s)"
6050                                  "(objectClass=%s))",
6051                                  escape_username,
6052                                  LDAP_OBJ_POSIXACCOUNT,
6053                                  LDAP_OBJ_SAMBASAMACCOUNT);
6054
6055         TALLOC_FREE(escape_username);
6056
6057         if (filter == NULL) {
6058                 return NT_STATUS_NO_MEMORY;
6059         }
6060
6061         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
6062         if (rc != LDAP_SUCCESS) {
6063                 DEBUG(0,("ldapsam_set_primary_group: user search failed!\n"));
6064                 return NT_STATUS_UNSUCCESSFUL;
6065         }
6066         talloc_autofree_ldapmsg(mem_ctx, result);
6067
6068         num_result = ldap_count_entries(priv2ld(ldap_state), result);
6069
6070         if (num_result == 0) {
6071                 DEBUG(0,("ldapsam_set_primary_group: user not found!\n"));
6072                 return NT_STATUS_NO_SUCH_USER;
6073         }
6074
6075         if (num_result > 1) {
6076                 DEBUG (0, ("ldapsam_set_primary_group: More than one user with name [%s] ?!\n", pdb_get_username(sampass)));
6077                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
6078         }
6079
6080         entry = ldap_first_entry(priv2ld(ldap_state), result);
6081         if (!entry) {
6082                 return NT_STATUS_UNSUCCESSFUL;
6083         }
6084
6085         /* retrieve the dn for later use */
6086         dn = smbldap_talloc_dn(mem_ctx, priv2ld(ldap_state), entry);
6087         if (!dn) {
6088                 DEBUG(0,("ldapsam_set_primary_group: Out of memory!\n"));
6089                 return NT_STATUS_NO_MEMORY;
6090         }
6091
6092         /* remove the old one, and add the new one, this way we do not risk races */
6093         smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "gidNumber", gidstr);
6094
6095         if (mods == NULL) {
6096                 return NT_STATUS_OK;
6097         }
6098
6099         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
6100
6101         if (rc != LDAP_SUCCESS) {
6102                 DEBUG(0,("ldapsam_set_primary_group: failed to modify [%s] primary group to [%s]\n",
6103                          pdb_get_username(sampass), gidstr));
6104                 return NT_STATUS_UNSUCCESSFUL;
6105         }
6106
6107         flush_pwnam_cache();
6108
6109         return NT_STATUS_OK;
6110 }
6111
6112
6113 /**********************************************************************
6114  trusted domains functions
6115  *********************************************************************/
6116
6117 static char *trusteddom_dn(struct ldapsam_privates *ldap_state,
6118                            const char *domain)
6119 {
6120         return talloc_asprintf(talloc_tos(), "sambaDomainName=%s,%s", domain,
6121                                ldap_state->domain_dn);
6122 }
6123
6124 static bool get_trusteddom_pw_int(struct ldapsam_privates *ldap_state,
6125                                   TALLOC_CTX *mem_ctx,
6126                                   const char *domain, LDAPMessage **entry)
6127 {
6128         int rc;
6129         char *filter;
6130         int scope = LDAP_SCOPE_SUBTREE;
6131         const char **attrs = NULL; /* NULL: get all attrs */
6132         int attrsonly = 0; /* 0: return values too */
6133         LDAPMessage *result = NULL;
6134         char *trusted_dn;
6135         uint32_t num_result;
6136
6137         filter = talloc_asprintf(talloc_tos(),
6138                                  "(&(objectClass=%s)(sambaDomainName=%s))",
6139                                  LDAP_OBJ_TRUSTDOM_PASSWORD, domain);
6140
6141         trusted_dn = trusteddom_dn(ldap_state, domain);
6142         if (trusted_dn == NULL) {
6143                 return False;
6144         }
6145         rc = smbldap_search(ldap_state->smbldap_state, trusted_dn, scope,
6146                             filter, attrs, attrsonly, &result);
6147
6148         if (result != NULL) {
6149                 talloc_autofree_ldapmsg(mem_ctx, result);
6150         }
6151
6152         if (rc == LDAP_NO_SUCH_OBJECT) {
6153                 *entry = NULL;
6154                 return True;
6155         }
6156
6157         if (rc != LDAP_SUCCESS) {
6158                 return False;
6159         }
6160
6161         num_result = ldap_count_entries(priv2ld(ldap_state), result);
6162
6163         if (num_result > 1) {
6164                 DEBUG(1, ("ldapsam_get_trusteddom_pw: more than one "
6165                           "%s object for domain '%s'?!\n",
6166                           LDAP_OBJ_TRUSTDOM_PASSWORD, domain));
6167                 return False;
6168         }
6169
6170         if (num_result == 0) {
6171                 DEBUG(1, ("ldapsam_get_trusteddom_pw: no "
6172                           "%s object for domain %s.\n",
6173                           LDAP_OBJ_TRUSTDOM_PASSWORD, domain));
6174                 *entry = NULL;
6175         } else {
6176                 *entry = ldap_first_entry(priv2ld(ldap_state), result);
6177         }
6178
6179         return True;
6180 }
6181
6182 static bool ldapsam_get_trusteddom_pw(struct pdb_methods *methods,
6183                                       const char *domain,
6184                                       char** pwd,
6185                                       struct dom_sid *sid,
6186                                       time_t *pass_last_set_time)
6187 {
6188         struct ldapsam_privates *ldap_state =
6189                 (struct ldapsam_privates *)methods->private_data;
6190         LDAPMessage *entry = NULL;
6191
6192         DEBUG(10, ("ldapsam_get_trusteddom_pw called for domain %s\n", domain));
6193
6194         if (!get_trusteddom_pw_int(ldap_state, talloc_tos(), domain, &entry) ||
6195             (entry == NULL))
6196         {
6197                 return False;
6198         }
6199
6200         /* password */
6201         if (pwd != NULL) {
6202                 char *pwd_str;
6203                 pwd_str = smbldap_talloc_single_attribute(priv2ld(ldap_state),
6204                                 entry, "sambaClearTextPassword", talloc_tos());
6205                 if (pwd_str == NULL) {
6206                         return False;
6207                 }
6208                 /* trusteddom_pw routines do not use talloc yet... */
6209                 *pwd = SMB_STRDUP(pwd_str);
6210                 if (*pwd == NULL) {
6211                         return False;
6212                 }
6213         }
6214
6215         /* last change time */
6216         if (pass_last_set_time != NULL) {
6217                 char *time_str;
6218                 time_str = smbldap_talloc_single_attribute(priv2ld(ldap_state),
6219                                 entry, "sambaPwdLastSet", talloc_tos());
6220                 if (time_str == NULL) {
6221                         return False;
6222                 }
6223                 *pass_last_set_time = (time_t)atol(time_str);
6224         }
6225
6226         /* domain sid */
6227         if (sid != NULL) {
6228                 char *sid_str;
6229                 struct dom_sid dom_sid;
6230                 sid_str = smbldap_talloc_single_attribute(priv2ld(ldap_state),
6231                                                           entry, "sambaSID",
6232                                                           talloc_tos());
6233                 if (sid_str == NULL) {
6234                         return False;
6235                 }
6236                 if (!string_to_sid(&dom_sid, sid_str)) {
6237                         return False;
6238                 }
6239                 sid_copy(sid, &dom_sid);
6240         }
6241
6242         return True;
6243 }
6244
6245 static bool ldapsam_set_trusteddom_pw(struct pdb_methods *methods,
6246                                       const char* domain,
6247                                       const char* pwd,
6248                                       const struct dom_sid *sid)
6249 {
6250         struct ldapsam_privates *ldap_state =
6251                 (struct ldapsam_privates *)methods->private_data;
6252         LDAPMessage *entry = NULL;
6253         LDAPMod **mods = NULL;
6254         char *prev_pwd = NULL;
6255         char *trusted_dn = NULL;
6256         int rc;
6257
6258         DEBUG(10, ("ldapsam_set_trusteddom_pw called for domain %s\n", domain));
6259
6260         /*
6261          * get the current entry (if there is one) in order to put the
6262          * current password into the previous password attribute
6263          */
6264         if (!get_trusteddom_pw_int(ldap_state, talloc_tos(), domain, &entry)) {
6265                 return False;
6266         }
6267
6268         mods = NULL;
6269         smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
6270                          LDAP_OBJ_TRUSTDOM_PASSWORD);
6271         smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaDomainName",
6272                          domain);
6273         smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaSID",
6274                          sid_string_tos(sid));
6275         smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaPwdLastSet",
6276                          talloc_asprintf(talloc_tos(), "%li", (long int)time(NULL)));
6277         smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
6278                          "sambaClearTextPassword", pwd);
6279
6280         if (entry != NULL) {
6281                 prev_pwd = smbldap_talloc_single_attribute(priv2ld(ldap_state),
6282                                 entry, "sambaClearTextPassword", talloc_tos());
6283                 if (prev_pwd != NULL) {
6284                         smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
6285                                          "sambaPreviousClearTextPassword",
6286                                          prev_pwd);
6287                 }
6288         }
6289
6290         talloc_autofree_ldapmod(talloc_tos(), mods);
6291
6292         trusted_dn = trusteddom_dn(ldap_state, domain);
6293         if (trusted_dn == NULL) {
6294                 return False;
6295         }
6296         if (entry == NULL) {
6297                 rc = smbldap_add(ldap_state->smbldap_state, trusted_dn, mods);
6298         } else {
6299                 rc = smbldap_modify(ldap_state->smbldap_state, trusted_dn, mods);
6300         }
6301
6302         if (rc != LDAP_SUCCESS) {
6303                 DEBUG(1, ("error writing trusted domain password!\n"));
6304                 return False;
6305         }
6306
6307         return True;
6308 }
6309
6310 static bool ldapsam_del_trusteddom_pw(struct pdb_methods *methods,
6311                                       const char *domain)
6312 {
6313         int rc;
6314         struct ldapsam_privates *ldap_state =
6315                 (struct ldapsam_privates *)methods->private_data;
6316         LDAPMessage *entry = NULL;
6317         const char *trusted_dn;
6318
6319         if (!get_trusteddom_pw_int(ldap_state, talloc_tos(), domain, &entry)) {
6320                 return False;
6321         }
6322
6323         if (entry == NULL) {
6324                 DEBUG(5, ("ldapsam_del_trusteddom_pw: no such trusted domain: "
6325                           "%s\n", domain));
6326                 return True;
6327         }
6328
6329         trusted_dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state),
6330                                        entry);
6331         if (trusted_dn == NULL) {
6332                 DEBUG(0,("ldapsam_del_trusteddom_pw: Out of memory!\n"));
6333                 return False;
6334         }
6335
6336         rc = smbldap_delete(ldap_state->smbldap_state, trusted_dn);
6337         if (rc != LDAP_SUCCESS) {
6338                 return False;
6339         }
6340
6341         return True;
6342 }
6343
6344 static NTSTATUS ldapsam_enum_trusteddoms(struct pdb_methods *methods,
6345                                          TALLOC_CTX *mem_ctx,
6346                                          uint32_t *num_domains,
6347                                          struct trustdom_info ***domains)
6348 {
6349         int rc;
6350         struct ldapsam_privates *ldap_state =
6351                 (struct ldapsam_privates *)methods->private_data;
6352         char *filter;
6353         int scope = LDAP_SCOPE_SUBTREE;
6354         const char *attrs[] = { "sambaDomainName", "sambaSID", NULL };
6355         int attrsonly = 0; /* 0: return values too */
6356         LDAPMessage *result = NULL;
6357         LDAPMessage *entry = NULL;
6358
6359         filter = talloc_asprintf(talloc_tos(), "(objectClass=%s)",
6360                                  LDAP_OBJ_TRUSTDOM_PASSWORD);
6361
6362         rc = smbldap_search(ldap_state->smbldap_state,
6363                             ldap_state->domain_dn,
6364                             scope,
6365                             filter,
6366                             attrs,
6367                             attrsonly,
6368                             &result);
6369
6370         if (result != NULL) {
6371                 talloc_autofree_ldapmsg(mem_ctx, result);
6372         }
6373
6374         if (rc != LDAP_SUCCESS) {
6375                 return NT_STATUS_UNSUCCESSFUL;
6376         }
6377
6378         *num_domains = 0;
6379         if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *, 1))) {
6380                 DEBUG(1, ("talloc failed\n"));
6381                 return NT_STATUS_NO_MEMORY;
6382         }
6383
6384         for (entry = ldap_first_entry(priv2ld(ldap_state), result);
6385              entry != NULL;
6386              entry = ldap_next_entry(priv2ld(ldap_state), entry))
6387         {
6388                 char *dom_name, *dom_sid_str;
6389                 struct trustdom_info *dom_info;
6390
6391                 dom_info = TALLOC_P(*domains, struct trustdom_info);
6392                 if (dom_info == NULL) {
6393                         DEBUG(1, ("talloc failed\n"));
6394                         return NT_STATUS_NO_MEMORY;
6395                 }
6396
6397                 dom_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
6398                                                            entry,
6399                                                            "sambaDomainName",
6400                                                            talloc_tos());
6401                 if (dom_name == NULL) {
6402                         DEBUG(1, ("talloc failed\n"));
6403                         return NT_STATUS_NO_MEMORY;
6404                 }
6405                 dom_info->name = dom_name;
6406
6407                 dom_sid_str = smbldap_talloc_single_attribute(
6408                                         priv2ld(ldap_state), entry, "sambaSID",
6409                                         talloc_tos());
6410                 if (dom_sid_str == NULL) {
6411                         DEBUG(1, ("talloc failed\n"));
6412                         return NT_STATUS_NO_MEMORY;
6413                 }
6414                 if (!string_to_sid(&dom_info->sid, dom_sid_str)) {
6415                         DEBUG(1, ("Error calling string_to_sid on SID %s\n",
6416                                   dom_sid_str));
6417                         return NT_STATUS_UNSUCCESSFUL;
6418                 }
6419
6420                 ADD_TO_ARRAY(*domains, struct trustdom_info *, dom_info,
6421                              domains, num_domains);
6422
6423                 if (*domains == NULL) {
6424                         DEBUG(1, ("talloc failed\n"));
6425                         return NT_STATUS_NO_MEMORY;
6426                 }
6427         }
6428
6429         DEBUG(5, ("ldapsam_enum_trusteddoms: got %d domains\n", *num_domains));
6430         return NT_STATUS_OK;
6431 }
6432
6433
6434 /**********************************************************************
6435  Housekeeping
6436  *********************************************************************/
6437
6438 static void free_private_data(void **vp) 
6439 {
6440         struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
6441
6442         smbldap_free_struct(&(*ldap_state)->smbldap_state);
6443
6444         if ((*ldap_state)->result != NULL) {
6445                 ldap_msgfree((*ldap_state)->result);
6446                 (*ldap_state)->result = NULL;
6447         }
6448         if ((*ldap_state)->domain_dn != NULL) {
6449                 SAFE_FREE((*ldap_state)->domain_dn);
6450         }
6451
6452         *ldap_state = NULL;
6453
6454         /* No need to free any further, as it is talloc()ed */
6455 }
6456
6457 /*********************************************************************
6458  Intitalise the parts of the pdb_methods structure that are common to 
6459  all pdb_ldap modes
6460 *********************************************************************/
6461
6462 static NTSTATUS pdb_init_ldapsam_common(struct pdb_methods **pdb_method, const char *location)
6463 {
6464         NTSTATUS nt_status;
6465         struct ldapsam_privates *ldap_state;
6466
6467         if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
6468                 return nt_status;
6469         }
6470
6471         (*pdb_method)->name = "ldapsam";
6472
6473         (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
6474         (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
6475         (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
6476         (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
6477         (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
6478         (*pdb_method)->rename_sam_account = ldapsam_rename_sam_account;
6479
6480         (*pdb_method)->getgrsid = ldapsam_getgrsid;
6481         (*pdb_method)->getgrgid = ldapsam_getgrgid;
6482         (*pdb_method)->getgrnam = ldapsam_getgrnam;
6483         (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
6484         (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
6485         (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
6486         (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
6487
6488         (*pdb_method)->get_account_policy = ldapsam_get_account_policy;
6489         (*pdb_method)->set_account_policy = ldapsam_set_account_policy;
6490
6491         (*pdb_method)->get_seq_num = ldapsam_get_seq_num;
6492
6493         (*pdb_method)->capabilities = ldapsam_capabilities;
6494         (*pdb_method)->new_rid = ldapsam_new_rid;
6495
6496         (*pdb_method)->get_trusteddom_pw = ldapsam_get_trusteddom_pw;
6497         (*pdb_method)->set_trusteddom_pw = ldapsam_set_trusteddom_pw;
6498         (*pdb_method)->del_trusteddom_pw = ldapsam_del_trusteddom_pw;
6499         (*pdb_method)->enum_trusteddoms = ldapsam_enum_trusteddoms;
6500
6501         /* TODO: Setup private data and free */
6502
6503         if ( !(ldap_state = TALLOC_ZERO_P(*pdb_method, struct ldapsam_privates)) ) {
6504                 DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n"));
6505                 return NT_STATUS_NO_MEMORY;
6506         }
6507
6508         nt_status = smbldap_init(*pdb_method, pdb_get_event_context(),
6509                                  location, &ldap_state->smbldap_state);
6510
6511         if ( !NT_STATUS_IS_OK(nt_status) ) {
6512                 return nt_status;
6513         }
6514
6515         if ( !(ldap_state->domain_name = talloc_strdup(*pdb_method, get_global_sam_name()) ) ) {
6516                 return NT_STATUS_NO_MEMORY;
6517         }
6518
6519         (*pdb_method)->private_data = ldap_state;
6520
6521         (*pdb_method)->free_private_data = free_private_data;
6522
6523         return NT_STATUS_OK;
6524 }
6525
6526 /**********************************************************************
6527  Initialise the 'compat' mode for pdb_ldap
6528  *********************************************************************/
6529
6530 NTSTATUS pdb_init_ldapsam_compat(struct pdb_methods **pdb_method, const char *location)
6531 {
6532         NTSTATUS nt_status;
6533         struct ldapsam_privates *ldap_state;
6534         char *uri = talloc_strdup( NULL, location );
6535
6536         trim_char( uri, '\"', '\"' );
6537         nt_status = pdb_init_ldapsam_common( pdb_method, uri );
6538         if ( uri )
6539                 TALLOC_FREE( uri );
6540
6541         if ( !NT_STATUS_IS_OK(nt_status) ) {
6542                 return nt_status;
6543         }
6544
6545         (*pdb_method)->name = "ldapsam_compat";
6546
6547         ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
6548         ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
6549
6550         sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
6551
6552         return NT_STATUS_OK;
6553 }
6554
6555 /**********************************************************************
6556  Initialise the normal mode for pdb_ldap
6557  *********************************************************************/
6558
6559 NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
6560 {
6561         NTSTATUS nt_status;
6562         struct ldapsam_privates *ldap_state = NULL;
6563         uint32_t alg_rid_base;
6564         char *alg_rid_base_string = NULL;
6565         LDAPMessage *result = NULL;
6566         LDAPMessage *entry = NULL;
6567         struct dom_sid ldap_domain_sid;
6568         struct dom_sid secrets_domain_sid;
6569         char *domain_sid_string = NULL;
6570         char *dn = NULL;
6571         char *uri = talloc_strdup( NULL, location );
6572
6573         trim_char( uri, '\"', '\"' );
6574         nt_status = pdb_init_ldapsam_common(pdb_method, uri);
6575
6576         TALLOC_FREE(uri);
6577
6578         if (!NT_STATUS_IS_OK(nt_status)) {
6579                 return nt_status;
6580         }
6581
6582         (*pdb_method)->name = "ldapsam";
6583
6584         (*pdb_method)->add_aliasmem = ldapsam_add_aliasmem;
6585         (*pdb_method)->del_aliasmem = ldapsam_del_aliasmem;
6586         (*pdb_method)->enum_aliasmem = ldapsam_enum_aliasmem;
6587         (*pdb_method)->enum_alias_memberships = ldapsam_alias_memberships;
6588         (*pdb_method)->search_users = ldapsam_search_users;
6589         (*pdb_method)->search_groups = ldapsam_search_groups;
6590         (*pdb_method)->search_aliases = ldapsam_search_aliases;
6591
6592         if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
6593                 (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
6594                 (*pdb_method)->enum_group_memberships =
6595                         ldapsam_enum_group_memberships;
6596                 (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
6597                 (*pdb_method)->sid_to_id = ldapsam_sid_to_id;
6598                 (*pdb_method)->uid_to_sid = ldapsam_uid_to_sid;
6599                 (*pdb_method)->gid_to_sid = ldapsam_gid_to_sid;
6600
6601                 if (lp_parm_bool(-1, "ldapsam", "editposix", False)) {
6602                         (*pdb_method)->create_user = ldapsam_create_user;
6603                         (*pdb_method)->delete_user = ldapsam_delete_user;
6604                         (*pdb_method)->create_dom_group = ldapsam_create_dom_group;
6605                         (*pdb_method)->delete_dom_group = ldapsam_delete_dom_group;
6606                         (*pdb_method)->add_groupmem = ldapsam_add_groupmem;
6607                         (*pdb_method)->del_groupmem = ldapsam_del_groupmem;
6608                         (*pdb_method)->set_unix_primary_group = ldapsam_set_primary_group;
6609                 }
6610         }
6611
6612         ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
6613         ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
6614
6615         /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
6616
6617         nt_status = smbldap_search_domain_info(ldap_state->smbldap_state,
6618                                                &result,
6619                                                ldap_state->domain_name, True);
6620
6621         if ( !NT_STATUS_IS_OK(nt_status) ) {
6622                 DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain "
6623                           "info, nor add one to the domain\n"));
6624                 DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, "
6625                              "will be unable to allocate new users/groups, "
6626                              "and will risk BDCs having inconsistant SIDs\n"));
6627                 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
6628                 return NT_STATUS_OK;
6629         }
6630
6631         /* Given that the above might fail, everything below this must be
6632          * optional */
6633
6634         entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
6635                                  result);
6636         if (!entry) {
6637                 DEBUG(0, ("pdb_init_ldapsam: Could not get domain info "
6638                           "entry\n"));
6639                 ldap_msgfree(result);
6640                 return NT_STATUS_UNSUCCESSFUL;
6641         }
6642
6643         dn = smbldap_talloc_dn(talloc_tos(), ldap_state->smbldap_state->ldap_struct, entry);
6644         if (!dn) {
6645                 ldap_msgfree(result);
6646                 return NT_STATUS_UNSUCCESSFUL;
6647         }
6648
6649         ldap_state->domain_dn = smb_xstrdup(dn);
6650         TALLOC_FREE(dn);
6651
6652         domain_sid_string = smbldap_talloc_single_attribute(
6653                     ldap_state->smbldap_state->ldap_struct,
6654                     entry,
6655                     get_userattr_key2string(ldap_state->schema_ver,
6656                                             LDAP_ATTR_USER_SID),
6657                     talloc_tos());
6658
6659         if (domain_sid_string) {
6660                 bool found_sid;
6661                 if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
6662                         DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be "
6663                                   "read as a valid SID\n", domain_sid_string));
6664                         ldap_msgfree(result);
6665                         TALLOC_FREE(domain_sid_string);
6666                         return NT_STATUS_INVALID_PARAMETER;
6667                 }
6668                 found_sid = secrets_fetch_domain_sid(ldap_state->domain_name,
6669                                                      &secrets_domain_sid);
6670                 if (!found_sid || !sid_equal(&secrets_domain_sid,
6671                                              &ldap_domain_sid)) {
6672                         DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain "
6673                                   "%s based on pdb_ldap results %s -> %s\n",
6674                                   ldap_state->domain_name,
6675                                   sid_string_dbg(&secrets_domain_sid),
6676                                   sid_string_dbg(&ldap_domain_sid)));
6677
6678                         /* reset secrets.tdb sid */
6679                         secrets_store_domain_sid(ldap_state->domain_name,
6680                                                  &ldap_domain_sid);
6681                         DEBUG(1, ("New global sam SID: %s\n",
6682                                   sid_string_dbg(get_global_sam_sid())));
6683                 }
6684                 sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
6685                 TALLOC_FREE(domain_sid_string);
6686         }
6687
6688         alg_rid_base_string = smbldap_talloc_single_attribute(
6689                     ldap_state->smbldap_state->ldap_struct,
6690                     entry,
6691                     get_attr_key2string( dominfo_attr_list,
6692                                          LDAP_ATTR_ALGORITHMIC_RID_BASE ),
6693                     talloc_tos());
6694         if (alg_rid_base_string) {
6695                 alg_rid_base = (uint32_t)atol(alg_rid_base_string);
6696                 if (alg_rid_base != algorithmic_rid_base()) {
6697                         DEBUG(0, ("The value of 'algorithmic RID base' has "
6698                                   "changed since the LDAP\n"
6699                                   "database was initialised.  Aborting. \n"));
6700                         ldap_msgfree(result);
6701                         TALLOC_FREE(alg_rid_base_string);
6702                         return NT_STATUS_UNSUCCESSFUL;
6703                 }
6704                 TALLOC_FREE(alg_rid_base_string);
6705         }
6706         ldap_msgfree(result);
6707
6708         return NT_STATUS_OK;
6709 }
6710
6711 NTSTATUS pdb_ldap_init(void)
6712 {
6713         NTSTATUS nt_status;
6714         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
6715                 return nt_status;
6716
6717         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
6718                 return nt_status;
6719
6720         /* Let pdb_nds register backends */
6721         pdb_nds_init();
6722
6723         return NT_STATUS_OK;
6724 }