s3-libads: use ldap_init_fd() to initialize a ldap session if possible
[bbaumbach/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 "passdb.h"
48 #include "../libcli/auth/libcli_auth.h"
49 #include "secrets.h"
50 #include "idmap_cache.h"
51 #include "../libcli/security/security.h"
52 #include "../lib/util/util_pw.h"
53 #include "lib/winbind_util.h"
54 #include "librpc/gen_ndr/idmap.h"
55 #include "lib/param/loadparm.h"
56 #include "lib/util_sid_passdb.h"
57
58 #undef DBGC_CLASS
59 #define DBGC_CLASS DBGC_PASSDB
60
61 #include <lber.h>
62 #include <ldap.h>
63
64
65 #include "smbldap.h"
66 #include "passdb/pdb_ldap.h"
67 #include "passdb/pdb_nds.h"
68 #include "passdb/pdb_ldap_util.h"
69 #include "passdb/pdb_ldap_schema.h"
70
71 /**********************************************************************
72  Simple helper function to make stuff better readable
73  **********************************************************************/
74
75 LDAP *priv2ld(struct ldapsam_privates *priv)
76 {
77         return smbldap_get_ldap(priv->smbldap_state);
78 }
79
80 /**********************************************************************
81  Get the attribute name given a user schame version.
82  **********************************************************************/
83  
84 static const char* get_userattr_key2string( int schema_ver, int key )
85 {
86         switch ( schema_ver ) {
87                 case SCHEMAVER_SAMBASAMACCOUNT:
88                         return get_attr_key2string( attrib_map_v30, key );
89
90                 default:
91                         DEBUG(0,("get_userattr_key2string: unknown schema version specified\n"));
92                         break;
93         }
94         return NULL;
95 }
96
97 /**********************************************************************
98  Return the list of attribute names given a user schema version.
99 **********************************************************************/
100
101 const char** get_userattr_list( TALLOC_CTX *mem_ctx, int schema_ver )
102 {
103         switch ( schema_ver ) {
104                 case SCHEMAVER_SAMBASAMACCOUNT:
105                         return get_attr_list( mem_ctx, attrib_map_v30 );
106                 default:
107                         DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
108                         break;
109         }
110
111         return NULL;
112 }
113
114 /**************************************************************************
115  Return the list of attribute names to delete given a user schema version.
116 **************************************************************************/
117
118 static const char** get_userattr_delete_list( TALLOC_CTX *mem_ctx,
119                                               int schema_ver )
120 {
121         switch ( schema_ver ) {
122                 case SCHEMAVER_SAMBASAMACCOUNT:
123                         return get_attr_list( mem_ctx,
124                                               attrib_map_to_delete_v30 );
125                 default:
126                         DEBUG(0,("get_userattr_delete_list: unknown schema version specified!\n"));
127                         break;
128         }
129
130         return NULL;
131 }
132
133
134 /*******************************************************************
135  Generate the LDAP search filter for the objectclass based on the 
136  version of the schema we are using.
137 ******************************************************************/
138
139 static const char* get_objclass_filter( int schema_ver )
140 {
141         fstring objclass_filter;
142         char *result;
143
144         switch( schema_ver ) {
145                 case SCHEMAVER_SAMBASAMACCOUNT:
146                         fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT );
147                         break;
148                 default:
149                         DEBUG(0,("get_objclass_filter: Invalid schema version specified!\n"));
150                         objclass_filter[0] = '\0';
151                         break;
152         }
153
154         result = talloc_strdup(talloc_tos(), objclass_filter);
155         SMB_ASSERT(result != NULL);
156         return result;
157 }
158
159 /*****************************************************************
160  Scan a sequence number off OpenLDAP's syncrepl contextCSN
161 ******************************************************************/
162
163 static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_num)
164 {
165         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
166         NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
167         LDAPMessage *msg = NULL;
168         LDAPMessage *entry = NULL;
169         TALLOC_CTX *mem_ctx;
170         char **values = NULL;
171         int rc, num_result, num_values, rid;
172         char *suffix = NULL;
173         char *tok;
174         const char *p;
175         const char **attrs;
176
177         /* Unfortunatly there is no proper way to detect syncrepl-support in
178          * smbldap_connect_system(). The syncrepl OIDs are submitted for publication
179          * but do not show up in the root-DSE yet. Neither we can query the
180          * subschema-context for the syncProviderSubentry or syncConsumerSubentry
181          * objectclass. Currently we require lp_ldap_suffix() to show up as
182          * namingContext.  -  Guenther
183          */
184
185         if (!lp_parm_bool(-1, "ldapsam", "syncrepl_seqnum", False)) {
186                 return ntstatus;
187         }
188
189         if (!seq_num) {
190                 DEBUG(3,("ldapsam_get_seq_num: no sequence_number\n"));
191                 return ntstatus;
192         }
193
194         if (!smbldap_has_naming_context(
195                     smbldap_get_ldap(ldap_state->smbldap_state),
196                     lp_ldap_suffix())) {
197                 DEBUG(3,("ldapsam_get_seq_num: DIT not configured to hold %s "
198                          "as top-level namingContext\n", lp_ldap_suffix()));
199                 return ntstatus;
200         }
201
202         mem_ctx = talloc_init("ldapsam_get_seq_num");
203
204         if (mem_ctx == NULL)
205                 return NT_STATUS_NO_MEMORY;
206
207         if ((attrs = talloc_array(mem_ctx, const char *, 2)) == NULL) {
208                 ntstatus = NT_STATUS_NO_MEMORY;
209                 goto done;
210         }
211
212         /* if we got a syncrepl-rid (up to three digits long) we speak with a consumer */
213         rid = lp_parm_int(-1, "ldapsam", "syncrepl_rid", -1);
214         if (rid > 0) {
215
216                 /* consumer syncreplCookie: */
217                 /* csn=20050126161620Z#0000001#00#00000 */
218                 attrs[0] = talloc_strdup(mem_ctx, "syncreplCookie");
219                 attrs[1] = NULL;
220                 suffix = talloc_asprintf(mem_ctx,
221                                 "cn=syncrepl%d,%s", rid, lp_ldap_suffix());
222                 if (!suffix) {
223                         ntstatus = NT_STATUS_NO_MEMORY;
224                         goto done;
225                 }
226         } else {
227
228                 /* provider contextCSN */
229                 /* 20050126161620Z#000009#00#000000 */
230                 attrs[0] = talloc_strdup(mem_ctx, "contextCSN");
231                 attrs[1] = NULL;
232                 suffix = talloc_asprintf(mem_ctx,
233                                 "cn=ldapsync,%s", lp_ldap_suffix());
234
235                 if (!suffix) {
236                         ntstatus = NT_STATUS_NO_MEMORY;
237                         goto done;
238                 }
239         }
240
241         rc = smbldap_search(ldap_state->smbldap_state, suffix,
242                             LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &msg);
243
244         if (rc != LDAP_SUCCESS) {
245                 goto done;
246         }
247
248         num_result = ldap_count_entries(
249                 smbldap_get_ldap(ldap_state->smbldap_state), msg);
250         if (num_result != 1) {
251                 DEBUG(3,("ldapsam_get_seq_num: Expected one entry, got %d\n", num_result));
252                 goto done;
253         }
254
255         entry = ldap_first_entry(
256                 smbldap_get_ldap(ldap_state->smbldap_state), msg);
257         if (entry == NULL) {
258                 DEBUG(3,("ldapsam_get_seq_num: Could not retrieve entry\n"));
259                 goto done;
260         }
261
262         values = ldap_get_values(
263                 smbldap_get_ldap(ldap_state->smbldap_state), entry, attrs[0]);
264         if (values == NULL) {
265                 DEBUG(3,("ldapsam_get_seq_num: no values\n"));
266                 goto done;
267         }
268
269         num_values = ldap_count_values(values);
270         if (num_values == 0) {
271                 DEBUG(3,("ldapsam_get_seq_num: not a single value\n"));
272                 goto done;
273         }
274
275         p = values[0];
276         if (!next_token_talloc(mem_ctx, &p, &tok, "#")) {
277                 DEBUG(0,("ldapsam_get_seq_num: failed to parse sequence number\n"));
278                 goto done;
279         }
280
281         p = tok;
282         if (!strncmp(p, "csn=", strlen("csn=")))
283                 p += strlen("csn=");
284
285         DEBUG(10,("ldapsam_get_seq_num: got %s: %s\n", attrs[0], p));
286
287         *seq_num = generalized_to_unix_time(p);
288
289         /* very basic sanity check */
290         if (*seq_num <= 0) {
291                 DEBUG(3,("ldapsam_get_seq_num: invalid sequence number: %d\n", 
292                         (int)*seq_num));
293                 goto done;
294         }
295
296         ntstatus = NT_STATUS_OK;
297
298  done:
299         if (values != NULL)
300                 ldap_value_free(values);
301         if (msg != NULL)
302                 ldap_msgfree(msg);
303         if (mem_ctx)
304                 talloc_destroy(mem_ctx);
305
306         return ntstatus;
307 }
308
309 /*******************************************************************
310  Run the search by name.
311 ******************************************************************/
312
313 int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state,
314                                           const char *user,
315                                           LDAPMessage ** result,
316                                           const char **attr)
317 {
318         char *filter = NULL;
319         char *escape_user = escape_ldap_string(talloc_tos(), user);
320         int ret = -1;
321
322         if (!escape_user) {
323                 return LDAP_NO_MEMORY;
324         }
325
326         /*
327          * in the filter expression, replace %u with the real name
328          * so in ldap filter, %u MUST exist :-)
329          */
330         filter = talloc_asprintf(talloc_tos(), "(&%s%s)", "(uid=%u)",
331                 get_objclass_filter(ldap_state->schema_ver));
332         if (!filter) {
333                 TALLOC_FREE(escape_user);
334                 return LDAP_NO_MEMORY;
335         }
336         /*
337          * have to use this here because $ is filtered out
338          * in string_sub
339          */
340
341         filter = talloc_all_string_sub(talloc_tos(),
342                                 filter, "%u", escape_user);
343         TALLOC_FREE(escape_user);
344         if (!filter) {
345                 return LDAP_NO_MEMORY;
346         }
347
348         ret = smbldap_search_suffix(ldap_state->smbldap_state,
349                         filter, attr, result);
350         TALLOC_FREE(filter);
351         return ret;
352 }
353
354 /*******************************************************************
355  Run the search by SID.
356 ******************************************************************/
357
358 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
359                                  const struct dom_sid *sid, LDAPMessage ** result,
360                                  const char **attr)
361 {
362         char *filter = NULL;
363         int rc;
364         struct dom_sid_buf sid_string;
365
366         filter = talloc_asprintf(talloc_tos(), "(&(%s=%s)%s)",
367                 get_userattr_key2string(ldap_state->schema_ver,
368                         LDAP_ATTR_USER_SID),
369                 dom_sid_str_buf(sid, &sid_string),
370                 get_objclass_filter(ldap_state->schema_ver));
371         if (!filter) {
372                 return LDAP_NO_MEMORY;
373         }
374
375         rc = smbldap_search_suffix(ldap_state->smbldap_state,
376                         filter, attr, result);
377
378         TALLOC_FREE(filter);
379         return rc;
380 }
381
382 /*******************************************************************
383  Delete complete object or objectclass and attrs from
384  object found in search_result depending on lp_ldap_delete_dn
385 ******************************************************************/
386
387 static int ldapsam_delete_entry(struct ldapsam_privates *priv,
388                                 TALLOC_CTX *mem_ctx,
389                                 LDAPMessage *entry,
390                                 const char *objectclass,
391                                 const char **attrs)
392 {
393         LDAPMod **mods = NULL;
394         char *name;
395         const char *dn;
396         BerElement *ptr = NULL;
397
398         dn = smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry);
399         if (dn == NULL) {
400                 return LDAP_NO_MEMORY;
401         }
402
403         if (lp_ldap_delete_dn()) {
404                 return smbldap_delete(priv->smbldap_state, dn);
405         }
406
407         /* Ok, delete only the SAM attributes */
408
409         for (name = ldap_first_attribute(priv2ld(priv), entry, &ptr);
410              name != NULL;
411              name = ldap_next_attribute(priv2ld(priv), entry, ptr)) {
412                 const char **attrib;
413
414                 /* We are only allowed to delete the attributes that
415                    really exist. */
416
417                 for (attrib = attrs; *attrib != NULL; attrib++) {
418                         if (strequal(*attrib, name)) {
419                                 DEBUG(10, ("ldapsam_delete_entry: deleting "
420                                            "attribute %s\n", name));
421                                 smbldap_set_mod(&mods, LDAP_MOD_DELETE, name,
422                                                 NULL);
423                         }
424                 }
425                 ldap_memfree(name);
426         }
427
428         if (ptr != NULL) {
429                 ber_free(ptr, 0);
430         }
431
432         smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
433         smbldap_talloc_autofree_ldapmod(mem_ctx, mods);
434
435         return smbldap_modify(priv->smbldap_state, dn, mods);
436 }
437
438 static time_t ldapsam_get_entry_timestamp( struct ldapsam_privates *ldap_state, LDAPMessage * entry)
439 {
440         char *temp;
441         struct tm tm;
442
443         temp = smbldap_talloc_single_attribute(
444                 smbldap_get_ldap(ldap_state->smbldap_state), entry,
445                 get_userattr_key2string(ldap_state->schema_ver,
446                                         LDAP_ATTR_MOD_TIMESTAMP),
447                         talloc_tos());
448         if (!temp) {
449                 return (time_t) 0;
450         }
451
452         if ( !strptime(temp, "%Y%m%d%H%M%SZ", &tm)) {
453                 DEBUG(2,("ldapsam_get_entry_timestamp: strptime failed on: %s\n",
454                         (char*)temp));
455                 TALLOC_FREE(temp);
456                 return (time_t) 0;
457         }
458         TALLOC_FREE(temp);
459         tzset();
460         return timegm(&tm);
461 }
462
463 /**********************************************************************
464  Initialize struct samu from an LDAP query.
465  (Based on init_sam_from_buffer in pdb_tdb.c)
466 *********************************************************************/
467
468 static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
469                                 struct samu * sampass,
470                                 LDAPMessage * entry)
471 {
472         time_t  logon_time,
473                         logoff_time,
474                         kickoff_time,
475                         pass_last_set_time,
476                         pass_can_change_time,
477                         ldap_entry_time,
478                         bad_password_time;
479         char *username = NULL,
480                         *domain = NULL,
481                         *nt_username = NULL,
482                         *fullname = NULL,
483                         *homedir = NULL,
484                         *dir_drive = NULL,
485                         *logon_script = NULL,
486                         *profile_path = NULL,
487                         *acct_desc = NULL,
488                         *workstations = NULL,
489                         *munged_dial = NULL;
490         uint32_t                user_rid;
491         uint8_t         smblmpwd[LM_HASH_LEN],
492                         smbntpwd[NT_HASH_LEN];
493         bool            use_samba_attrs = True;
494         uint16_t                logon_divs;
495         uint16_t                bad_password_count = 0,
496                         logon_count = 0;
497         uint32_t hours_len;
498         uint8_t         hours[MAX_HOURS_LEN];
499         char *temp = NULL;
500         struct login_cache cache_entry;
501         uint32_t                pwHistLen;
502         bool expand_explicit = lp_passdb_expand_explicit();
503         bool ret = false;
504         TALLOC_CTX *ctx = talloc_init("init_sam_from_ldap");
505
506         if (!ctx) {
507                 return false;
508         }
509         if (sampass == NULL || ldap_state == NULL || entry == NULL) {
510                 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
511                 goto fn_exit;
512         }
513
514         if (priv2ld(ldap_state) == NULL) {
515                 DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->"
516                           "ldap_struct is NULL!\n"));
517                 goto fn_exit;
518         }
519
520         if (!(username = smbldap_talloc_first_attribute(priv2ld(ldap_state),
521                                         entry,
522                                         "uid",
523                                         ctx))) {
524                 DEBUG(1, ("init_sam_from_ldap: No uid attribute found for "
525                           "this user!\n"));
526                 goto fn_exit;
527         }
528
529         DEBUG(2, ("init_sam_from_ldap: Entry found for user: %s\n", username));
530
531         nt_username = talloc_strdup(ctx, username);
532         if (!nt_username) {
533                 goto fn_exit;
534         }
535
536         domain = talloc_strdup(ctx, ldap_state->domain_name);
537         if (!domain) {
538                 goto fn_exit;
539         }
540
541         pdb_set_username(sampass, username, PDB_SET);
542
543         pdb_set_domain(sampass, domain, PDB_DEFAULT);
544         pdb_set_nt_username(sampass, nt_username, PDB_SET);
545
546         /* deal with different attributes between the schema first */
547
548         if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ) {
549                 if ((temp = smbldap_talloc_single_attribute(
550                                 smbldap_get_ldap(ldap_state->smbldap_state),
551                                 entry,
552                                 get_userattr_key2string(ldap_state->schema_ver,
553                                         LDAP_ATTR_USER_SID),
554                                 ctx))!=NULL) {
555                         pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
556                 }
557         } else {
558                 if ((temp = smbldap_talloc_single_attribute(
559                                 smbldap_get_ldap(ldap_state->smbldap_state),
560                                 entry,
561                                 get_userattr_key2string(ldap_state->schema_ver,
562                                         LDAP_ATTR_USER_RID),
563                                 ctx))!=NULL) {
564                         user_rid = (uint32_t)atol(temp);
565                         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
566                 }
567         }
568
569         if (IS_SAM_DEFAULT(sampass, PDB_USERSID)) {
570                 DEBUG(1, ("init_sam_from_ldap: no %s or %s attribute found for this user %s\n", 
571                         get_userattr_key2string(ldap_state->schema_ver,
572                                 LDAP_ATTR_USER_SID),
573                         get_userattr_key2string(ldap_state->schema_ver,
574                                 LDAP_ATTR_USER_RID),
575                         username));
576                 return False;
577         }
578
579         temp = smbldap_talloc_single_attribute(
580                         smbldap_get_ldap(ldap_state->smbldap_state),
581                         entry,
582                         get_userattr_key2string(ldap_state->schema_ver,
583                                 LDAP_ATTR_PWD_LAST_SET),
584                         ctx);
585         if (temp) {
586                 pass_last_set_time = (time_t) atol(temp);
587                 pdb_set_pass_last_set_time(sampass,
588                                 pass_last_set_time, PDB_SET);
589         }
590
591         temp = smbldap_talloc_single_attribute(
592                         smbldap_get_ldap(ldap_state->smbldap_state),
593                         entry,
594                         get_userattr_key2string(ldap_state->schema_ver,
595                                 LDAP_ATTR_LOGON_TIME),
596                         ctx);
597         if (temp) {
598                 logon_time = (time_t) atol(temp);
599                 pdb_set_logon_time(sampass, logon_time, PDB_SET);
600         }
601
602         temp = smbldap_talloc_single_attribute(
603                         smbldap_get_ldap(ldap_state->smbldap_state),
604                         entry,
605                         get_userattr_key2string(ldap_state->schema_ver,
606                                 LDAP_ATTR_LOGOFF_TIME),
607                         ctx);
608         if (temp) {
609                 logoff_time = (time_t) atol(temp);
610                 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
611         }
612
613         temp = smbldap_talloc_single_attribute(
614                         smbldap_get_ldap(ldap_state->smbldap_state),
615                         entry,
616                         get_userattr_key2string(ldap_state->schema_ver,
617                                 LDAP_ATTR_KICKOFF_TIME),
618                         ctx);
619         if (temp) {
620                 kickoff_time = (time_t) atol(temp);
621                 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
622         }
623
624         temp = smbldap_talloc_single_attribute(
625                         smbldap_get_ldap(ldap_state->smbldap_state),
626                         entry,
627                         get_userattr_key2string(ldap_state->schema_ver,
628                                 LDAP_ATTR_PWD_CAN_CHANGE),
629                         ctx);
630         if (temp) {
631                 pass_can_change_time = (time_t) atol(temp);
632                 pdb_set_pass_can_change_time(sampass,
633                                 pass_can_change_time, PDB_SET);
634         }
635
636         /* recommend that 'gecos' and 'displayName' should refer to the same
637          * attribute OID.  userFullName depreciated, only used by Samba
638          * primary rules of LDAP: don't make a new attribute when one is already defined
639          * that fits your needs; using cn then displayName rather than 'userFullName'
640          */
641
642         fullname = smbldap_talloc_single_attribute(
643                         smbldap_get_ldap(ldap_state->smbldap_state),
644                         entry,
645                         get_userattr_key2string(ldap_state->schema_ver,
646                                 LDAP_ATTR_DISPLAY_NAME),
647                         ctx);
648         if (fullname) {
649                 pdb_set_fullname(sampass, fullname, PDB_SET);
650         } else {
651                 fullname = smbldap_talloc_single_attribute(
652                                 smbldap_get_ldap(ldap_state->smbldap_state),
653                                 entry,
654                                 get_userattr_key2string(ldap_state->schema_ver,
655                                         LDAP_ATTR_CN),
656                                 ctx);
657                 if (fullname) {
658                         pdb_set_fullname(sampass, fullname, PDB_SET);
659                 }
660         }
661
662         dir_drive = smbldap_talloc_single_attribute(
663                         smbldap_get_ldap(ldap_state->smbldap_state),
664                         entry,
665                         get_userattr_key2string(ldap_state->schema_ver,
666                                 LDAP_ATTR_HOME_DRIVE),
667                         ctx);
668         if (dir_drive) {
669                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
670         } else {
671                 pdb_set_dir_drive( sampass, lp_logon_drive(), PDB_DEFAULT );
672         }
673
674         homedir = smbldap_talloc_single_attribute(
675                         smbldap_get_ldap(ldap_state->smbldap_state),
676                         entry,
677                         get_userattr_key2string(ldap_state->schema_ver,
678                                 LDAP_ATTR_HOME_PATH),
679                         ctx);
680         if (homedir) {
681                 if (expand_explicit) {
682                         homedir = talloc_sub_basic(ctx,
683                                                 username,
684                                                 domain,
685                                                 homedir);
686                         if (!homedir) {
687                                 goto fn_exit;
688                         }
689                 }
690                 pdb_set_homedir(sampass, homedir, PDB_SET);
691         } else {
692                 pdb_set_homedir(sampass,
693                         talloc_sub_basic(ctx, username, domain,
694                                          lp_logon_home()),
695                         PDB_DEFAULT);
696         }
697
698         logon_script = smbldap_talloc_single_attribute(
699                         smbldap_get_ldap(ldap_state->smbldap_state),
700                         entry,
701                         get_userattr_key2string(ldap_state->schema_ver,
702                                 LDAP_ATTR_LOGON_SCRIPT),
703                         ctx);
704         if (logon_script) {
705                 if (expand_explicit) {
706                         logon_script = talloc_sub_basic(ctx,
707                                                 username,
708                                                 domain,
709                                                 logon_script);
710                         if (!logon_script) {
711                                 goto fn_exit;
712                         }
713                 }
714                 pdb_set_logon_script(sampass, logon_script, PDB_SET);
715         } else {
716                 pdb_set_logon_script(sampass,
717                         talloc_sub_basic(ctx, username, domain,
718                                          lp_logon_script()),
719                         PDB_DEFAULT );
720         }
721
722         profile_path = smbldap_talloc_single_attribute(
723                         smbldap_get_ldap(ldap_state->smbldap_state),
724                         entry,
725                         get_userattr_key2string(ldap_state->schema_ver,
726                                 LDAP_ATTR_PROFILE_PATH),
727                         ctx);
728         if (profile_path) {
729                 if (expand_explicit) {
730                         profile_path = talloc_sub_basic(ctx,
731                                                 username,
732                                                 domain,
733                                                 profile_path);
734                         if (!profile_path) {
735                                 goto fn_exit;
736                         }
737                 }
738                 pdb_set_profile_path(sampass, profile_path, PDB_SET);
739         } else {
740                 pdb_set_profile_path(sampass,
741                         talloc_sub_basic(ctx, username, domain,
742                                           lp_logon_path()),
743                         PDB_DEFAULT );
744         }
745
746         acct_desc = smbldap_talloc_single_attribute(
747                         smbldap_get_ldap(ldap_state->smbldap_state),
748                         entry,
749                         get_userattr_key2string(ldap_state->schema_ver,
750                                 LDAP_ATTR_DESC),
751                         ctx);
752         if (acct_desc) {
753                 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
754         }
755
756         workstations = smbldap_talloc_single_attribute(
757                         smbldap_get_ldap(ldap_state->smbldap_state),
758                         entry,
759                         get_userattr_key2string(ldap_state->schema_ver,
760                                 LDAP_ATTR_USER_WKS),
761                         ctx);
762         if (workstations) {
763                 pdb_set_workstations(sampass, workstations, PDB_SET);
764         }
765
766         munged_dial = smbldap_talloc_single_attribute(
767                         smbldap_get_ldap(ldap_state->smbldap_state),
768                         entry,
769                         get_userattr_key2string(ldap_state->schema_ver,
770                                 LDAP_ATTR_MUNGED_DIAL),
771                         ctx);
772         if (munged_dial) {
773                 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
774         }
775
776         /* FIXME: hours stuff should be cleaner */
777
778         logon_divs = 168;
779         hours_len = 21;
780         memset(hours, 0xff, hours_len);
781
782         if (ldap_state->is_nds_ldap) {
783                 char *user_dn;
784                 size_t pwd_len;
785                 char clear_text_pw[512];
786
787                 /* Make call to Novell eDirectory ldap extension to get clear text password.
788                         NOTE: This will only work if we have an SSL connection to eDirectory. */
789                 user_dn = smbldap_talloc_dn(
790                         ctx, smbldap_get_ldap(ldap_state->smbldap_state),
791                         entry);
792                 if (user_dn != NULL) {
793                         DEBUG(3, ("init_sam_from_ldap: smbldap_talloc_dn(ctx, %s) returned '%s'\n", username, user_dn));
794
795                         pwd_len = sizeof(clear_text_pw);
796                         if (pdb_nds_get_password(ldap_state->smbldap_state, user_dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) {
797                                 nt_lm_owf_gen(clear_text_pw, smbntpwd, smblmpwd);
798                                 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET)) {
799                                         TALLOC_FREE(user_dn);
800                                         return False;
801                                 }
802                                 ZERO_STRUCT(smblmpwd);
803                                 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET)) {
804                                         TALLOC_FREE(user_dn);
805                                         return False;
806                                 }
807                                 ZERO_STRUCT(smbntpwd);
808                                 use_samba_attrs = False;
809                         }
810
811                         TALLOC_FREE(user_dn);
812
813                 } else {
814                         DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username));
815                 }
816         }
817
818         if (use_samba_attrs) {
819                 temp = smbldap_talloc_single_attribute(
820                                 smbldap_get_ldap(ldap_state->smbldap_state),
821                                 entry,
822                                 get_userattr_key2string(ldap_state->schema_ver,
823                                         LDAP_ATTR_LMPW),
824                                 ctx);
825                 if (temp) {
826                         pdb_gethexpwd(temp, smblmpwd);
827                         memset((char *)temp, '\0', strlen(temp)+1);
828                         if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET)) {
829                                 goto fn_exit;
830                         }
831                         ZERO_STRUCT(smblmpwd);
832                 }
833
834                 temp = smbldap_talloc_single_attribute(
835                                 smbldap_get_ldap(ldap_state->smbldap_state),
836                                 entry,
837                                 get_userattr_key2string(ldap_state->schema_ver,
838                                         LDAP_ATTR_NTPW),
839                                 ctx);
840                 if (temp) {
841                         pdb_gethexpwd(temp, smbntpwd);
842                         memset((char *)temp, '\0', strlen(temp)+1);
843                         if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET)) {
844                                 goto fn_exit;
845                         }
846                         ZERO_STRUCT(smbntpwd);
847                 }
848         }
849
850         pwHistLen = 0;
851
852         pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
853         if (pwHistLen > 0){
854                 uint8_t *pwhist = NULL;
855                 int i;
856                 char *history_string = talloc_array(ctx, char,
857                                                 MAX_PW_HISTORY_LEN*64);
858
859                 if (!history_string) {
860                         goto fn_exit;
861                 }
862
863                 pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN);
864
865                 pwhist = talloc_zero_array(ctx, uint8_t,
866                                            pwHistLen * PW_HISTORY_ENTRY_LEN);
867                 if (pwhist == NULL) {
868                         DEBUG(0, ("init_sam_from_ldap: talloc failed!\n"));
869                         goto fn_exit;
870                 }
871
872                 if (smbldap_get_single_attribute(
873                                 smbldap_get_ldap(ldap_state->smbldap_state),
874                                 entry,
875                                 get_userattr_key2string(ldap_state->schema_ver,
876                                         LDAP_ATTR_PWD_HISTORY),
877                                 history_string,
878                                 MAX_PW_HISTORY_LEN*64)) {
879                         bool hex_failed = false;
880                         for (i = 0; i < pwHistLen; i++){
881                                 /* Get the 16 byte salt. */
882                                 if (!pdb_gethexpwd(&history_string[i*64],
883                                         &pwhist[i*PW_HISTORY_ENTRY_LEN])) {
884                                         hex_failed = true;
885                                         break;
886                                 }
887                                 /* Get the 16 byte MD5 hash of salt+passwd. */
888                                 if (!pdb_gethexpwd(&history_string[(i*64)+32],
889                                         &pwhist[(i*PW_HISTORY_ENTRY_LEN)+
890                                                 PW_HISTORY_SALT_LEN])) {
891                                         hex_failed = True;
892                                         break;
893                                 }
894                         }
895                         if (hex_failed) {
896                                 DEBUG(2,("init_sam_from_ldap: Failed to get password history for user %s\n",
897                                         username));
898                                 memset(pwhist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
899                         }
900                 }
901                 if (!pdb_set_pw_history(sampass, pwhist, pwHistLen, PDB_SET)){
902                         goto fn_exit;
903                 }
904         }
905
906         temp = smbldap_talloc_single_attribute(
907                         smbldap_get_ldap(ldap_state->smbldap_state),
908                         entry,
909                         get_userattr_key2string(ldap_state->schema_ver,
910                                 LDAP_ATTR_ACB_INFO),
911                         ctx);
912         if (temp) {
913                 uint32_t acct_ctrl = 0;
914                 acct_ctrl = pdb_decode_acct_ctrl(temp);
915
916                 if (acct_ctrl == 0) {
917                         acct_ctrl |= ACB_NORMAL;
918                 }
919
920                 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
921         }
922
923         pdb_set_hours_len(sampass, hours_len, PDB_SET);
924         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
925
926         temp = smbldap_talloc_single_attribute(
927                         smbldap_get_ldap(ldap_state->smbldap_state),
928                         entry,
929                         get_userattr_key2string(ldap_state->schema_ver,
930                                 LDAP_ATTR_BAD_PASSWORD_COUNT),
931                         ctx);
932         if (temp) {
933                 bad_password_count = (uint32_t) atol(temp);
934                 pdb_set_bad_password_count(sampass,
935                                 bad_password_count, PDB_SET);
936         }
937
938         temp = smbldap_talloc_single_attribute(
939                         smbldap_get_ldap(ldap_state->smbldap_state),
940                         entry,
941                         get_userattr_key2string(ldap_state->schema_ver,
942                                 LDAP_ATTR_BAD_PASSWORD_TIME),
943                         ctx);
944         if (temp) {
945                 bad_password_time = (time_t) atol(temp);
946                 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
947         }
948
949
950         temp = smbldap_talloc_single_attribute(
951                         smbldap_get_ldap(ldap_state->smbldap_state),
952                         entry,
953                         get_userattr_key2string(ldap_state->schema_ver,
954                                 LDAP_ATTR_LOGON_COUNT),
955                         ctx);
956         if (temp) {
957                 logon_count = (uint32_t) atol(temp);
958                 pdb_set_logon_count(sampass, logon_count, PDB_SET);
959         }
960
961         /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
962
963         temp = smbldap_talloc_single_attribute(
964                         smbldap_get_ldap(ldap_state->smbldap_state),
965                         entry,
966                         get_userattr_key2string(ldap_state->schema_ver,
967                                 LDAP_ATTR_LOGON_HOURS),
968                         ctx);
969         if (temp) {
970                 pdb_gethexhours(temp, hours);
971                 memset((char *)temp, '\0', strlen(temp) +1);
972                 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
973                 ZERO_STRUCT(hours);
974         }
975
976         if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
977                 struct passwd unix_pw;
978                 bool have_uid = false;
979                 bool have_gid = false;
980                 struct dom_sid mapped_gsid;
981                 const struct dom_sid *primary_gsid;
982                 struct unixid id;
983                 int error = 0;
984
985                 ZERO_STRUCT(unix_pw);
986
987                 unix_pw.pw_name = username;
988                 unix_pw.pw_passwd = discard_const_p(char, "x");
989
990                 temp = smbldap_talloc_single_attribute(
991                                 priv2ld(ldap_state),
992                                 entry,
993                                 "uidNumber",
994                                 ctx);
995                 if (temp) {
996                         /* We've got a uid, feed the cache */
997                         unix_pw.pw_uid = smb_strtoul(temp,
998                                                      NULL,
999                                                      10,
1000                                                      &error,
1001                                                      SMB_STR_STANDARD);
1002                         if (error != 0) {
1003                                 DBG_ERR("Failed to convert UID\n");
1004                                 goto fn_exit;
1005                         }
1006                         have_uid = true;
1007                 }
1008                 temp = smbldap_talloc_single_attribute(
1009                                 priv2ld(ldap_state),
1010                                 entry,
1011                                 "gidNumber",
1012                                 ctx);
1013                 if (temp) {
1014                         /* We've got a uid, feed the cache */
1015                         unix_pw.pw_gid = smb_strtoul(temp,
1016                                                      NULL,
1017                                                      10,
1018                                                      &error,
1019                                                      SMB_STR_STANDARD);
1020                         if (error != 0) {
1021                                 DBG_ERR("Failed to convert GID\n");
1022                                 goto fn_exit;
1023                         }
1024                         have_gid = true;
1025                 }
1026                 unix_pw.pw_gecos = smbldap_talloc_single_attribute(
1027                                 priv2ld(ldap_state),
1028                                 entry,
1029                                 "gecos",
1030                                 ctx);
1031                 if (unix_pw.pw_gecos == NULL) {
1032                         unix_pw.pw_gecos = fullname;
1033                 }
1034                 unix_pw.pw_dir = smbldap_talloc_single_attribute(
1035                                 priv2ld(ldap_state),
1036                                 entry,
1037                                 "homeDirectory",
1038                                 ctx);
1039                 if (unix_pw.pw_dir == NULL) {
1040                         unix_pw.pw_dir = discard_const_p(char, "");
1041                 }
1042                 unix_pw.pw_shell = smbldap_talloc_single_attribute(
1043                                 priv2ld(ldap_state),
1044                                 entry,
1045                                 "loginShell",
1046                                 ctx);
1047                 if (unix_pw.pw_shell == NULL) {
1048                         unix_pw.pw_shell = discard_const_p(char, "");
1049                 }
1050
1051                 if (have_uid && have_gid) {
1052                         sampass->unix_pw = tcopy_passwd(sampass, &unix_pw);
1053                 } else {
1054                         sampass->unix_pw = Get_Pwnam_alloc(sampass, unix_pw.pw_name);
1055                 }
1056
1057                 if (sampass->unix_pw == NULL) {
1058                         DEBUG(0,("init_sam_from_ldap: Failed to find Unix account for %s\n",
1059                                  pdb_get_username(sampass)));
1060                         goto fn_exit;
1061                 }
1062
1063                 id.id = sampass->unix_pw->pw_uid;
1064                 id.type = ID_TYPE_UID;
1065
1066                 idmap_cache_set_sid2unixid(pdb_get_user_sid(sampass), &id);
1067
1068                 gid_to_sid(&mapped_gsid, sampass->unix_pw->pw_gid);
1069                 primary_gsid = pdb_get_group_sid(sampass);
1070                 if (primary_gsid && dom_sid_equal(primary_gsid, &mapped_gsid)) {
1071                         id.id = sampass->unix_pw->pw_gid;
1072                         id.type = ID_TYPE_GID;
1073
1074                         idmap_cache_set_sid2unixid(primary_gsid, &id);
1075                 }
1076         }
1077
1078         /* check the timestamp of the cache vs ldap entry */
1079         if (!(ldap_entry_time = ldapsam_get_entry_timestamp(ldap_state,
1080                                                             entry))) {
1081                 ret = true;
1082                 goto fn_exit;
1083         }
1084
1085         /* see if we have newer updates */
1086         if (!login_cache_read(sampass, &cache_entry)) {
1087                 DEBUG (9, ("No cache entry, bad count = %u, bad time = %u\n",
1088                            (unsigned int)pdb_get_bad_password_count(sampass),
1089                            (unsigned int)pdb_get_bad_password_time(sampass)));
1090                 ret = true;
1091                 goto fn_exit;
1092         }
1093
1094         DEBUG(7, ("ldap time is %u, cache time is %u, bad time = %u\n",
1095                   (unsigned int)ldap_entry_time,
1096                   (unsigned int)cache_entry.entry_timestamp,
1097                   (unsigned int)cache_entry.bad_password_time));
1098
1099         if (ldap_entry_time > cache_entry.entry_timestamp) {
1100                 /* cache is older than directory , so
1101                    we need to delete the entry but allow the
1102                    fields to be written out */
1103                 login_cache_delentry(sampass);
1104         } else {
1105                 /* read cache in */
1106                 pdb_set_acct_ctrl(sampass,
1107                                   pdb_get_acct_ctrl(sampass) |
1108                                   (cache_entry.acct_ctrl & ACB_AUTOLOCK),
1109                                   PDB_SET);
1110                 pdb_set_bad_password_count(sampass,
1111                                            cache_entry.bad_password_count,
1112                                            PDB_SET);
1113                 pdb_set_bad_password_time(sampass,
1114                                           cache_entry.bad_password_time,
1115                                           PDB_SET);
1116         }
1117
1118         ret = true;
1119
1120   fn_exit:
1121
1122         TALLOC_FREE(ctx);
1123         return ret;
1124 }
1125
1126 /**********************************************************************
1127  Initialize the ldap db from a struct samu. Called on update.
1128  (Based on init_buffer_from_sam in pdb_tdb.c)
1129 *********************************************************************/
1130
1131 static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
1132                                 LDAPMessage *existing,
1133                                 LDAPMod *** mods, struct samu * sampass,
1134                                 bool (*need_update)(const struct samu *,
1135                                                     enum pdb_elements))
1136 {
1137         char *temp = NULL;
1138
1139         if (mods == NULL || sampass == NULL) {
1140                 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1141                 return False;
1142         }
1143
1144         *mods = NULL;
1145
1146         /*
1147          * took out adding "objectclass: sambaAccount"
1148          * do this on a per-mod basis
1149          */
1150         if (need_update(sampass, PDB_USERNAME)) {
1151                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1152                                  existing, mods,
1153                                  "uid", pdb_get_username(sampass));
1154                 if (ldap_state->is_nds_ldap) {
1155                         smbldap_make_mod(
1156                                 smbldap_get_ldap(ldap_state->smbldap_state),
1157                                 existing, mods,
1158                                 "cn", pdb_get_username(sampass));
1159                         smbldap_make_mod(
1160                                 smbldap_get_ldap(ldap_state->smbldap_state),
1161                                 existing, mods,
1162                                 "sn", pdb_get_username(sampass));
1163                 }
1164         }
1165
1166         DEBUG(2, ("init_ldap_from_sam: Setting entry for user: %s\n", pdb_get_username(sampass)));
1167
1168         /* only update the RID if we actually need to */
1169         if (need_update(sampass, PDB_USERSID)) {
1170                 struct dom_sid_buf sid_str;
1171                 const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
1172
1173                 switch ( ldap_state->schema_ver ) {
1174                         case SCHEMAVER_SAMBASAMACCOUNT:
1175                                 smbldap_make_mod(
1176                                         smbldap_get_ldap(
1177                                                 ldap_state->smbldap_state),
1178                                         existing, mods,
1179                                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), 
1180                                         dom_sid_str_buf(user_sid, &sid_str));
1181                                 break;
1182
1183                         default:
1184                                 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
1185                                 break;
1186                 }
1187         }
1188
1189         /* we don't need to store the primary group RID - so leaving it
1190            'free' to hang off the unix primary group makes life easier */
1191
1192         if (need_update(sampass, PDB_GROUPSID)) {
1193                 struct dom_sid_buf sid_str;
1194                 const struct dom_sid *group_sid = pdb_get_group_sid(sampass);
1195
1196                 switch ( ldap_state->schema_ver ) {
1197                         case SCHEMAVER_SAMBASAMACCOUNT:
1198                                 smbldap_make_mod(
1199                                         smbldap_get_ldap(
1200                                                 ldap_state->smbldap_state),
1201                                         existing, mods,
1202                                         get_userattr_key2string(ldap_state->schema_ver, 
1203                                         LDAP_ATTR_PRIMARY_GROUP_SID),
1204                                         dom_sid_str_buf(group_sid, &sid_str));
1205                                 break;
1206
1207                         default:
1208                                 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
1209                                 break;
1210                 }
1211
1212         }
1213
1214         /* displayName, cn, and gecos should all be the same
1215          *  most easily accomplished by giving them the same OID
1216          *  gecos isn't set here b/c it should be handled by the
1217          *  add-user script
1218          *  We change displayName only and fall back to cn if
1219          *  it does not exist.
1220          */
1221
1222         if (need_update(sampass, PDB_FULLNAME))
1223                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1224                                  existing, mods,
1225                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), 
1226                         pdb_get_fullname(sampass));
1227
1228         if (need_update(sampass, PDB_ACCTDESC))
1229                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1230                                  existing, mods,
1231                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), 
1232                         pdb_get_acct_desc(sampass));
1233
1234         if (need_update(sampass, PDB_WORKSTATIONS))
1235                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1236                                  existing, mods,
1237                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), 
1238                         pdb_get_workstations(sampass));
1239
1240         if (need_update(sampass, PDB_MUNGEDDIAL))
1241                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1242                                  existing, mods,
1243                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MUNGED_DIAL), 
1244                         pdb_get_munged_dial(sampass));
1245
1246         if (need_update(sampass, PDB_SMBHOME))
1247                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1248                                  existing, mods,
1249                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), 
1250                         pdb_get_homedir(sampass));
1251
1252         if (need_update(sampass, PDB_DRIVE))
1253                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1254                                  existing, mods,
1255                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), 
1256                         pdb_get_dir_drive(sampass));
1257
1258         if (need_update(sampass, PDB_LOGONSCRIPT))
1259                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1260                                  existing, mods,
1261                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), 
1262                         pdb_get_logon_script(sampass));
1263
1264         if (need_update(sampass, PDB_PROFILE))
1265                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1266                                  existing, mods,
1267                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), 
1268                         pdb_get_profile_path(sampass));
1269
1270         if (asprintf(&temp, "%li", (long int)pdb_get_logon_time(sampass)) < 0) {
1271                 return false;
1272         }
1273         if (need_update(sampass, PDB_LOGONTIME))
1274                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1275                                  existing, mods,
1276                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp);
1277         SAFE_FREE(temp);
1278
1279         if (asprintf(&temp, "%li", (long int)pdb_get_logoff_time(sampass)) < 0) {
1280                 return false;
1281         }
1282         if (need_update(sampass, PDB_LOGOFFTIME))
1283                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1284                                  existing, mods,
1285                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp);
1286         SAFE_FREE(temp);
1287
1288         if (asprintf(&temp, "%li", (long int)pdb_get_kickoff_time(sampass)) < 0) {
1289                 return false;
1290         }
1291         if (need_update(sampass, PDB_KICKOFFTIME))
1292                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1293                                  existing, mods,
1294                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
1295         SAFE_FREE(temp);
1296
1297         if (asprintf(&temp, "%li", (long int)pdb_get_pass_can_change_time_noncalc(sampass)) < 0) {
1298                 return false;
1299         }
1300         if (need_update(sampass, PDB_CANCHANGETIME))
1301                 smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state),
1302                                  existing, mods,
1303                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
1304         SAFE_FREE(temp);
1305
1306         if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))
1307                         || (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
1308
1309                 if (need_update(sampass, PDB_LMPASSWD)) {
1310                         const uchar *lm_pw = pdb_get_lanman_passwd(sampass);
1311                         if (lm_pw) {
1312                                 char pwstr[34];
1313                                 pdb_sethexpwd(pwstr, lm_pw,
1314                                               pdb_get_acct_ctrl(sampass));
1315                                 smbldap_make_mod(
1316                                         smbldap_get_ldap(
1317                                                 ldap_state->smbldap_state),
1318                                         existing, mods,
1319                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), 
1320                                                  pwstr);
1321                         } else {
1322                                 smbldap_make_mod(
1323                                         smbldap_get_ldap(
1324                                                 ldap_state->smbldap_state),
1325                                         existing, mods,
1326                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), 
1327                                                  NULL);
1328                         }
1329                 }
1330                 if (need_update(sampass, PDB_NTPASSWD)) {
1331                         const uchar *nt_pw = pdb_get_nt_passwd(sampass);
1332                         if (nt_pw) {
1333                                 char pwstr[34];
1334                                 pdb_sethexpwd(pwstr, nt_pw,
1335                                               pdb_get_acct_ctrl(sampass));
1336                                 smbldap_make_mod(
1337                                         smbldap_get_ldap(
1338                                                 ldap_state->smbldap_state),
1339                                         existing, mods,
1340                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), 
1341                                                  pwstr);
1342                         } else {
1343                                 smbldap_make_mod(
1344                                         smbldap_get_ldap(
1345                                                 ldap_state->smbldap_state),
1346                                         existing, mods,
1347                                                  get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), 
1348                                                  NULL);
1349                         }
1350                 }
1351
1352                 if (need_update(sampass, PDB_PWHISTORY)) {
1353                         char *pwstr = NULL;
1354                         uint32_t pwHistLen = 0;
1355                         pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1356
1357                         pwstr = SMB_MALLOC_ARRAY(char, 1024);
1358                         if (!pwstr) {
1359                                 return false;
1360                         }
1361                         if (pwHistLen == 0) {
1362                                 /* Remove any password history from the LDAP store. */
1363                                 memset(pwstr, '0', 64); /* NOTE !!!! '0' *NOT '\0' */
1364                                 pwstr[64] = '\0';
1365                         } else {
1366                                 int i;
1367                                 uint32_t currHistLen = 0;
1368                                 const uint8_t *pwhist = pdb_get_pw_history(sampass, &currHistLen);
1369                                 if (pwhist != NULL) {
1370                                         /* We can only store (1024-1/64 password history entries. */
1371                                         pwHistLen = MIN(pwHistLen, ((1024-1)/64));
1372                                         for (i=0; i< pwHistLen && i < currHistLen; i++) {
1373                                                 /* Store the salt. */
1374                                                 pdb_sethexpwd(&pwstr[i*64], &pwhist[i*PW_HISTORY_ENTRY_LEN], 0);
1375                                                 /* Followed by the md5 hash of salt + md4 hash */
1376                                                 pdb_sethexpwd(&pwstr[(i*64)+32],
1377                                                         &pwhist[(i*PW_HISTORY_ENTRY_LEN)+PW_HISTORY_SALT_LEN], 0);
1378                                                 DEBUG(100, ("pwstr=%s\n", pwstr));
1379                                         }
1380                                 }
1381                         }
1382                         smbldap_make_mod(
1383                                 smbldap_get_ldap(ldap_state->smbldap_state),
1384                                 existing, mods,
1385                                          get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY), 
1386                                          pwstr);
1387                         SAFE_FREE(pwstr);
1388                 }
1389
1390                 if (need_update(sampass, PDB_PASSLASTSET)) {
1391                         if (asprintf(&temp, "%li",
1392                                 (long int)pdb_get_pass_last_set_time(sampass)) < 0) {
1393                                 return false;
1394                         }
1395                         smbldap_make_mod(
1396                                 smbldap_get_ldap(ldap_state->smbldap_state),
1397                                 existing, mods,
1398                                 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), 
1399                                 temp);
1400                         SAFE_FREE(temp);
1401                 }
1402         }
1403
1404         if (need_update(sampass, PDB_HOURS)) {
1405                 const uint8_t *hours = pdb_get_hours(sampass);
1406                 if (hours) {
1407                         char hourstr[44];
1408                         pdb_sethexhours(hourstr, hours);
1409                         smbldap_make_mod(
1410                                 smbldap_get_ldap(ldap_state->smbldap_state),
1411                                 existing,
1412                                 mods,
1413                                 get_userattr_key2string(ldap_state->schema_ver,
1414                                                 LDAP_ATTR_LOGON_HOURS),
1415                                 hourstr);
1416                 }
1417         }
1418
1419         if (need_update(sampass, PDB_ACCTCTRL))
1420                 smbldap_make_mod(
1421                         smbldap_get_ldap(ldap_state->smbldap_state),
1422                         existing, mods,
1423                         get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), 
1424                         pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), NEW_PW_FORMAT_SPACE_PADDED_LEN));
1425
1426         /* password lockout cache:
1427            - If we are now autolocking or clearing, we write to ldap
1428            - If we are clearing, we delete the cache entry
1429            - If the count is > 0, we update the cache
1430
1431            This even means when autolocking, we cache, just in case the
1432            update doesn't work, and we have to cache the autolock flag */
1433
1434         if (need_update(sampass, PDB_BAD_PASSWORD_COUNT))  /* &&
1435             need_update(sampass, PDB_BAD_PASSWORD_TIME)) */ {
1436                 uint16_t badcount = pdb_get_bad_password_count(sampass);
1437                 time_t badtime = pdb_get_bad_password_time(sampass);
1438                 uint32_t pol;
1439                 pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &pol);
1440
1441                 DEBUG(3, ("updating bad password fields, policy=%u, count=%u, time=%u\n",
1442                         (unsigned int)pol, (unsigned int)badcount, (unsigned int)badtime));
1443
1444                 if ((badcount >= pol) || (badcount == 0)) {
1445                         DEBUG(7, ("making mods to update ldap, count=%u, time=%u\n",
1446                                 (unsigned int)badcount, (unsigned int)badtime));
1447                         if (asprintf(&temp, "%li", (long)badcount) < 0) {
1448                                 return false;
1449                         }
1450                         smbldap_make_mod(
1451                                 smbldap_get_ldap(ldap_state->smbldap_state),
1452                                 existing, mods,
1453                                 get_userattr_key2string(
1454                                         ldap_state->schema_ver,
1455                                         LDAP_ATTR_BAD_PASSWORD_COUNT),
1456                                 temp);
1457                         SAFE_FREE(temp);
1458
1459                         if (asprintf(&temp, "%li", (long int)badtime) < 0) {
1460                                 return false;
1461                         }
1462                         smbldap_make_mod(
1463                                 smbldap_get_ldap(ldap_state->smbldap_state),
1464                                 existing, mods,
1465                                 get_userattr_key2string(
1466                                         ldap_state->schema_ver,
1467                                         LDAP_ATTR_BAD_PASSWORD_TIME),
1468                                 temp);
1469                         SAFE_FREE(temp);
1470                 }
1471                 if (badcount == 0) {
1472                         DEBUG(7, ("bad password count is reset, deleting login cache entry for %s\n", pdb_get_nt_username(sampass)));
1473                         login_cache_delentry(sampass);
1474                 } else {
1475                         struct login_cache cache_entry;
1476
1477                         cache_entry.entry_timestamp = time(NULL);
1478                         cache_entry.acct_ctrl = pdb_get_acct_ctrl(sampass);
1479                         cache_entry.bad_password_count = badcount;
1480                         cache_entry.bad_password_time = badtime;
1481
1482                         DEBUG(7, ("Updating bad password count and time in login cache\n"));
1483                         login_cache_write(sampass, &cache_entry);
1484                 }
1485         }
1486
1487         return True;
1488 }
1489
1490 /**********************************************************************
1491  End enumeration of the LDAP password list.
1492 *********************************************************************/
1493
1494 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1495 {
1496         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1497         if (ldap_state->result) {
1498                 ldap_msgfree(ldap_state->result);
1499                 ldap_state->result = NULL;
1500         }
1501 }
1502
1503 static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list,
1504                         const char *new_attr)
1505 {
1506         int i;
1507
1508         if (new_attr == NULL) {
1509                 return;
1510         }
1511
1512         for (i=0; (*attr_list)[i] != NULL; i++) {
1513                 ;
1514         }
1515
1516         (*attr_list) = talloc_realloc(mem_ctx, (*attr_list),
1517                                             const char *,  i+2);
1518         SMB_ASSERT((*attr_list) != NULL);
1519         (*attr_list)[i] = talloc_strdup((*attr_list), new_attr);
1520         (*attr_list)[i+1] = NULL;
1521 }
1522
1523 static void ldapsam_add_unix_attributes(TALLOC_CTX *mem_ctx,
1524                                         const char ***attr_list)
1525 {
1526         append_attr(mem_ctx, attr_list, "uidNumber");
1527         append_attr(mem_ctx, attr_list, "gidNumber");
1528         append_attr(mem_ctx, attr_list, "homeDirectory");
1529         append_attr(mem_ctx, attr_list, "loginShell");
1530         append_attr(mem_ctx, attr_list, "gecos");
1531 }
1532
1533 /**********************************************************************
1534 Get struct samu entry from LDAP by username.
1535 *********************************************************************/
1536
1537 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, struct samu *user, const char *sname)
1538 {
1539         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1540         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1541         LDAPMessage *result = NULL;
1542         LDAPMessage *entry = NULL;
1543         int count;
1544         const char ** attr_list;
1545         int rc;
1546
1547         attr_list = get_userattr_list( user, ldap_state->schema_ver );
1548         append_attr(user, &attr_list,
1549                     get_userattr_key2string(ldap_state->schema_ver,
1550                                             LDAP_ATTR_MOD_TIMESTAMP));
1551         ldapsam_add_unix_attributes(user, &attr_list);
1552         rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result,
1553                                            attr_list);
1554         TALLOC_FREE( attr_list );
1555
1556         if ( rc != LDAP_SUCCESS ) 
1557                 return NT_STATUS_NO_SUCH_USER;
1558
1559         count = ldap_count_entries(smbldap_get_ldap(ldap_state->smbldap_state),
1560                                    result);
1561
1562         if (count < 1) {
1563                 DEBUG(4, ("ldapsam_getsampwnam: Unable to locate user [%s] count=%d\n", sname, count));
1564                 ldap_msgfree(result);
1565                 return NT_STATUS_NO_SUCH_USER;
1566         } else if (count > 1) {
1567                 DEBUG(1, ("ldapsam_getsampwnam: Duplicate entries for this user [%s] Failing. count=%d\n", sname, count));
1568                 ldap_msgfree(result);
1569                 return NT_STATUS_NO_SUCH_USER;
1570         }
1571
1572         entry = ldap_first_entry(smbldap_get_ldap(ldap_state->smbldap_state),
1573                                  result);
1574         if (entry) {
1575                 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1576                         DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1577                         ldap_msgfree(result);
1578                         return NT_STATUS_NO_SUCH_USER;
1579                 }
1580                 pdb_set_backend_private_data(user, result, NULL,
1581                                              my_methods, PDB_CHANGED);
1582                 smbldap_talloc_autofree_ldapmsg(user, result);
1583                 ret = NT_STATUS_OK;
1584         } else {
1585                 ldap_msgfree(result);
1586         }
1587         return ret;
1588 }
1589
1590 static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, 
1591                                    const struct dom_sid *sid, LDAPMessage **result)
1592 {
1593         int rc = -1;
1594         const char ** attr_list;
1595
1596         switch ( ldap_state->schema_ver ) {
1597                 case SCHEMAVER_SAMBASAMACCOUNT: {
1598                         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1599                         if (tmp_ctx == NULL) {
1600                                 return LDAP_NO_MEMORY;
1601                         }
1602
1603                         attr_list = get_userattr_list(tmp_ctx,
1604                                                       ldap_state->schema_ver);
1605                         append_attr(tmp_ctx, &attr_list,
1606                                     get_userattr_key2string(
1607                                             ldap_state->schema_ver,
1608                                             LDAP_ATTR_MOD_TIMESTAMP));
1609                         ldapsam_add_unix_attributes(tmp_ctx, &attr_list);
1610                         rc = ldapsam_search_suffix_by_sid(ldap_state, sid,
1611                                                           result, attr_list);
1612                         TALLOC_FREE(tmp_ctx);
1613
1614                         if ( rc != LDAP_SUCCESS ) 
1615                                 return rc;
1616                         break;
1617                 }
1618
1619                 default:
1620                         DEBUG(0,("Invalid schema version specified\n"));
1621                         break;
1622         }
1623         return rc;
1624 }
1625
1626 /**********************************************************************
1627  Get struct samu entry from LDAP by SID.
1628 *********************************************************************/
1629
1630 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const struct dom_sid *sid)
1631 {
1632         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1633         LDAPMessage *result = NULL;
1634         LDAPMessage *entry = NULL;
1635         int count;
1636         int rc;
1637
1638         rc = ldapsam_get_ldap_user_by_sid(ldap_state, 
1639                                           sid, &result); 
1640         if (rc != LDAP_SUCCESS)
1641                 return NT_STATUS_NO_SUCH_USER;
1642
1643         count = ldap_count_entries(smbldap_get_ldap(ldap_state->smbldap_state),
1644                                    result);
1645
1646         if (count < 1) {
1647                 struct dom_sid_buf buf;
1648                 DEBUG(4, ("ldapsam_getsampwsid: Unable to locate SID [%s] "
1649                           "count=%d\n",
1650                           dom_sid_str_buf(sid, &buf),
1651                           count));
1652                 ldap_msgfree(result);
1653                 return NT_STATUS_NO_SUCH_USER;
1654         }  else if (count > 1) {
1655                 struct dom_sid_buf buf;
1656                 DEBUG(1, ("ldapsam_getsampwsid: More than one user with SID "
1657                           "[%s]. Failing. count=%d\n",
1658                           dom_sid_str_buf(sid, &buf),
1659                           count));
1660                 ldap_msgfree(result);
1661                 return NT_STATUS_NO_SUCH_USER;
1662         }
1663
1664         entry = ldap_first_entry(smbldap_get_ldap(ldap_state->smbldap_state),
1665                                  result);
1666         if (!entry) {
1667                 ldap_msgfree(result);
1668                 return NT_STATUS_NO_SUCH_USER;
1669         }
1670
1671         if (!init_sam_from_ldap(ldap_state, user, entry)) {
1672                 DEBUG(1,("ldapsam_getsampwsid: init_sam_from_ldap failed!\n"));
1673                 ldap_msgfree(result);
1674                 return NT_STATUS_NO_SUCH_USER;
1675         }
1676
1677         pdb_set_backend_private_data(user, result, NULL,
1678                                      my_methods, PDB_CHANGED);
1679         smbldap_talloc_autofree_ldapmsg(user, result);
1680         return NT_STATUS_OK;
1681 }       
1682
1683 /********************************************************************
1684  Do the actual modification - also change a plaintext passord if 
1685  it it set.
1686 **********************************************************************/
1687
1688 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, 
1689                                      struct samu *newpwd, char *dn,
1690                                      LDAPMod **mods, int ldap_op, 
1691                                      bool (*need_update)(const struct samu *, enum pdb_elements))
1692 {
1693         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1694         int rc;
1695
1696         if (!newpwd || !dn) {
1697                 return NT_STATUS_INVALID_PARAMETER;
1698         }
1699
1700         if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
1701                         (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
1702                         need_update(newpwd, PDB_PLAINTEXT_PW) &&
1703                         (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1704                 BerElement *ber;
1705                 struct berval *bv;
1706                 char *retoid = NULL;
1707                 struct berval *retdata = NULL;
1708                 char *utf8_password;
1709                 char *utf8_dn;
1710                 size_t converted_size;
1711                 int ret;
1712
1713                 if (!ldap_state->is_nds_ldap) {
1714
1715                         if (!smbldap_has_extension(
1716                                     smbldap_get_ldap(
1717                                             ldap_state->smbldap_state),
1718                                     LDAP_EXOP_MODIFY_PASSWD)) {
1719                                 DEBUG(2, ("ldap password change requested, but LDAP "
1720                                           "server does not support it -- ignoring\n"));
1721                                 return NT_STATUS_OK;
1722                         }
1723                 }
1724
1725                 if (!push_utf8_talloc(talloc_tos(), &utf8_password,
1726                                         pdb_get_plaintext_passwd(newpwd),
1727                                         &converted_size))
1728                 {
1729                         return NT_STATUS_NO_MEMORY;
1730                 }
1731
1732                 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1733                         TALLOC_FREE(utf8_password);
1734                         return NT_STATUS_NO_MEMORY;
1735                 }
1736
1737                 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1738                         DEBUG(0,("ber_alloc_t returns NULL\n"));
1739                         TALLOC_FREE(utf8_password);
1740                         TALLOC_FREE(utf8_dn);
1741                         return NT_STATUS_UNSUCCESSFUL;
1742                 }
1743
1744                 if ((ber_printf (ber, "{") < 0) ||
1745                     (ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
1746                                  utf8_dn) < 0)) {
1747                         DEBUG(0,("ldapsam_modify_entry: ber_printf returns a "
1748                                  "value <0\n"));
1749                         ber_free(ber,1);
1750                         TALLOC_FREE(utf8_dn);
1751                         TALLOC_FREE(utf8_password);
1752                         return NT_STATUS_UNSUCCESSFUL;
1753                 }
1754
1755                 if ((utf8_password != NULL) && (*utf8_password != '\0')) {
1756                         ret = ber_printf(ber, "ts}",
1757                                          LDAP_TAG_EXOP_MODIFY_PASSWD_NEW,
1758                                          utf8_password);
1759                 } else {
1760                         ret = ber_printf(ber, "}");
1761                 }
1762
1763                 if (ret < 0) {
1764                         DEBUG(0,("ldapsam_modify_entry: ber_printf returns a "
1765                                  "value <0\n"));
1766                         ber_free(ber,1);
1767                         TALLOC_FREE(utf8_dn);
1768                         TALLOC_FREE(utf8_password);
1769                         return NT_STATUS_UNSUCCESSFUL;
1770                 }
1771
1772                 if ((rc = ber_flatten (ber, &bv))<0) {
1773                         DEBUG(0,("ldapsam_modify_entry: ber_flatten returns a value <0\n"));
1774                         ber_free(ber,1);
1775                         TALLOC_FREE(utf8_dn);
1776                         TALLOC_FREE(utf8_password);
1777                         return NT_STATUS_UNSUCCESSFUL;
1778                 }
1779
1780                 TALLOC_FREE(utf8_dn);
1781                 TALLOC_FREE(utf8_password);
1782                 ber_free(ber, 1);
1783
1784                 if (!ldap_state->is_nds_ldap) {
1785                         rc = smbldap_extended_operation(ldap_state->smbldap_state, 
1786                                                         LDAP_EXOP_MODIFY_PASSWD,
1787                                                         bv, NULL, NULL, &retoid, 
1788                                                         &retdata);
1789                 } else {
1790                         rc = pdb_nds_set_password(ldap_state->smbldap_state, dn,
1791                                                         pdb_get_plaintext_passwd(newpwd));
1792                 }
1793                 if (rc != LDAP_SUCCESS) {
1794                         char *ld_error = NULL;
1795
1796                         if (rc == LDAP_OBJECT_CLASS_VIOLATION) {
1797                                 DEBUG(3, ("Could not set userPassword "
1798                                           "attribute due to an objectClass "
1799                                           "violation -- ignoring\n"));
1800                                 ber_bvfree(bv);
1801                                 return NT_STATUS_OK;
1802                         }
1803
1804                         ldap_get_option(
1805                                 smbldap_get_ldap(ldap_state->smbldap_state),
1806                                 LDAP_OPT_ERROR_STRING,
1807                                         &ld_error);
1808                         DEBUG(0,("ldapsam_modify_entry: LDAP Password could not be changed for user %s: %s\n\t%s\n",
1809                                 pdb_get_username(newpwd), ldap_err2string(rc), ld_error?ld_error:"unknown"));
1810                         SAFE_FREE(ld_error);
1811                         ber_bvfree(bv);
1812 #if defined(LDAP_CONSTRAINT_VIOLATION)
1813                         if (rc == LDAP_CONSTRAINT_VIOLATION)
1814                                 return NT_STATUS_PASSWORD_RESTRICTION;
1815 #endif
1816                         return NT_STATUS_UNSUCCESSFUL;
1817                 } else {
1818                         DEBUG(3,("ldapsam_modify_entry: LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1819 #ifdef DEBUG_PASSWORD
1820                         DEBUG(100,("ldapsam_modify_entry: LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
1821 #endif    
1822                         if (retdata)
1823                                 ber_bvfree(retdata);
1824                         if (retoid)
1825                                 ldap_memfree(retoid);
1826                 }
1827                 ber_bvfree(bv);
1828         }
1829
1830         if (!mods) {
1831                 DEBUG(5,("ldapsam_modify_entry: mods is empty: nothing to modify\n"));
1832                 /* may be password change below however */
1833         } else {
1834                 switch(ldap_op) {
1835                         case LDAP_MOD_ADD:
1836                                 if (ldap_state->is_nds_ldap) {
1837                                         smbldap_set_mod(&mods, LDAP_MOD_ADD,
1838                                                         "objectclass",
1839                                                         "inetOrgPerson");
1840                                 } else {
1841                                         smbldap_set_mod(&mods, LDAP_MOD_ADD,
1842                                                         "objectclass",
1843                                                         LDAP_OBJ_ACCOUNT);
1844                                 }
1845                                 rc = smbldap_add(ldap_state->smbldap_state,
1846                                                  dn, mods);
1847                                 break;
1848                         case LDAP_MOD_REPLACE:
1849                                 rc = smbldap_modify(ldap_state->smbldap_state,
1850                                                     dn ,mods);
1851                                 break;
1852                         default:
1853                                 DEBUG(0,("ldapsam_modify_entry: Wrong LDAP operation type: %d!\n",
1854                                          ldap_op));
1855                                 return NT_STATUS_INVALID_PARAMETER;
1856                 }
1857
1858                 if (rc!=LDAP_SUCCESS) {
1859                         return NT_STATUS_UNSUCCESSFUL;
1860                 }
1861         }
1862
1863         return NT_STATUS_OK;
1864 }
1865
1866 /**********************************************************************
1867  Delete entry from LDAP for username.
1868 *********************************************************************/
1869
1870 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods,
1871                                            struct samu * sam_acct)
1872 {
1873         struct ldapsam_privates *priv =
1874                 (struct ldapsam_privates *)my_methods->private_data;
1875         const char *sname;
1876         int rc;
1877         LDAPMessage *msg, *entry;
1878         NTSTATUS result = NT_STATUS_NO_MEMORY;
1879         const char **attr_list;
1880         TALLOC_CTX *mem_ctx;
1881
1882         if (!sam_acct) {
1883                 DEBUG(0, ("ldapsam_delete_sam_account: sam_acct was NULL!\n"));
1884                 return NT_STATUS_INVALID_PARAMETER;
1885         }
1886
1887         sname = pdb_get_username(sam_acct);
1888
1889         DEBUG(3, ("ldapsam_delete_sam_account: Deleting user %s from "
1890                   "LDAP.\n", sname));
1891
1892         mem_ctx = talloc_new(NULL);
1893         if (mem_ctx == NULL) {
1894                 DEBUG(0, ("talloc_new failed\n"));
1895                 goto done;
1896         }
1897
1898         attr_list = get_userattr_delete_list(mem_ctx, priv->schema_ver );
1899         if (attr_list == NULL) {
1900                 goto done;
1901         }
1902
1903         rc = ldapsam_search_suffix_by_name(priv, sname, &msg, attr_list);
1904
1905         if ((rc != LDAP_SUCCESS) ||
1906             (ldap_count_entries(priv2ld(priv), msg) != 1) ||
1907             ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
1908                 DEBUG(5, ("Could not find user %s\n", sname));
1909                 result = NT_STATUS_NO_SUCH_USER;
1910                 goto done;
1911         }
1912
1913         rc = ldapsam_delete_entry(
1914                 priv, mem_ctx, entry,
1915                 priv->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ?
1916                 LDAP_OBJ_SAMBASAMACCOUNT : 0,
1917                 attr_list);
1918
1919         result = (rc == LDAP_SUCCESS) ?
1920                 NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
1921
1922  done:
1923         TALLOC_FREE(mem_ctx);
1924         return result;
1925 }
1926
1927 /**********************************************************************
1928  Update struct samu.
1929 *********************************************************************/
1930
1931 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struct samu * newpwd)
1932 {
1933         NTSTATUS ret;
1934         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1935         int rc = 0;
1936         char *dn;
1937         LDAPMessage *result = NULL;
1938         LDAPMessage *entry = NULL;
1939         LDAPMod **mods = NULL;
1940         const char **attr_list;
1941
1942         result = (LDAPMessage *)pdb_get_backend_private_data(newpwd, my_methods);
1943         if (!result) {
1944                 attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
1945                 if (pdb_get_username(newpwd) == NULL) {
1946                         return NT_STATUS_INVALID_PARAMETER;
1947                 }
1948                 rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list );
1949                 TALLOC_FREE( attr_list );
1950                 if (rc != LDAP_SUCCESS) {
1951                         return NT_STATUS_UNSUCCESSFUL;
1952                 }
1953                 pdb_set_backend_private_data(newpwd, result, NULL,
1954                                              my_methods, PDB_CHANGED);
1955                 smbldap_talloc_autofree_ldapmsg(newpwd, result);
1956         }
1957
1958         if (ldap_count_entries(smbldap_get_ldap(ldap_state->smbldap_state),
1959                                result) == 0) {
1960                 DEBUG(0, ("ldapsam_update_sam_account: No user to modify!\n"));
1961                 return NT_STATUS_UNSUCCESSFUL;
1962         }
1963
1964         entry = ldap_first_entry(smbldap_get_ldap(ldap_state->smbldap_state),
1965                                  result);
1966         dn = smbldap_talloc_dn(talloc_tos(),
1967                                smbldap_get_ldap(ldap_state->smbldap_state),
1968                                entry);
1969         if (!dn) {
1970                 return NT_STATUS_UNSUCCESSFUL;
1971         }
1972
1973         DEBUG(4, ("ldapsam_update_sam_account: user %s to be modified has dn: %s\n", pdb_get_username(newpwd), dn));
1974
1975         if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1976                                 pdb_element_is_changed)) {
1977                 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1978                 TALLOC_FREE(dn);
1979                 if (mods != NULL)
1980                         ldap_mods_free(mods,True);
1981                 return NT_STATUS_UNSUCCESSFUL;
1982         }
1983
1984         if ((lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_ONLY)
1985             && (mods == NULL)) {
1986                 DEBUG(4,("ldapsam_update_sam_account: mods is empty: nothing to update for user: %s\n",
1987                          pdb_get_username(newpwd)));
1988                 TALLOC_FREE(dn);
1989                 return NT_STATUS_OK;
1990         }
1991
1992         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, pdb_element_is_changed);
1993
1994         if (mods != NULL) {
1995                 ldap_mods_free(mods,True);
1996         }
1997
1998         TALLOC_FREE(dn);
1999
2000         /*
2001          * We need to set the backend private data to NULL here. For example
2002          * setuserinfo level 25 does a pdb_update_sam_account twice on the
2003          * same one, and with the explicit delete / add logic for attribute
2004          * values the second time we would use the wrong "old" value which
2005          * does not exist in LDAP anymore. Thus the LDAP server would refuse
2006          * the update.
2007          * The existing LDAPMessage is still being auto-freed by the
2008          * destructor.
2009          */
2010         pdb_set_backend_private_data(newpwd, NULL, NULL, my_methods,
2011                                      PDB_CHANGED);
2012
2013         if (!NT_STATUS_IS_OK(ret)) {
2014                 return ret;
2015         }
2016
2017         DEBUG(2, ("ldapsam_update_sam_account: successfully modified uid = %s in the LDAP database\n",
2018                   pdb_get_username(newpwd)));
2019         return NT_STATUS_OK;
2020 }
2021
2022 /***************************************************************************
2023  Renames a struct samu
2024  - The "rename user script" has full responsibility for changing everything
2025 ***************************************************************************/
2026
2027 static NTSTATUS ldapsam_del_groupmem(struct pdb_methods *my_methods,
2028                                      TALLOC_CTX *tmp_ctx,
2029                                      uint32_t group_rid,
2030                                      uint32_t member_rid);
2031
2032 static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
2033                                                TALLOC_CTX *mem_ctx,
2034                                                struct samu *user,
2035                                                struct dom_sid **pp_sids,
2036                                                gid_t **pp_gids,
2037                                                uint32_t *p_num_groups);
2038
2039 static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
2040                                            struct samu *old_acct,
2041                                            const char *newname)
2042 {
2043         const struct loadparm_substitution *lp_sub =
2044                 loadparm_s3_global_substitution();
2045         const char *oldname;
2046         int rc;
2047         char *rename_script = NULL;
2048         fstring oldname_lower, newname_lower;
2049
2050         if (!old_acct) {
2051                 DEBUG(0, ("ldapsam_rename_sam_account: old_acct was NULL!\n"));
2052                 return NT_STATUS_INVALID_PARAMETER;
2053         }
2054         if (!newname) {
2055                 DEBUG(0, ("ldapsam_rename_sam_account: newname was NULL!\n"));
2056                 return NT_STATUS_INVALID_PARAMETER;
2057         }
2058
2059         oldname = pdb_get_username(old_acct);
2060
2061         /* rename the posix user */
2062         rename_script = lp_rename_user_script(talloc_tos(), lp_sub);
2063         if (rename_script == NULL) {
2064                 return NT_STATUS_NO_MEMORY;
2065         }
2066
2067         if (!(*rename_script)) {
2068                 TALLOC_FREE(rename_script);
2069                 return NT_STATUS_ACCESS_DENIED;
2070         }
2071
2072         DEBUG (3, ("ldapsam_rename_sam_account: Renaming user %s to %s.\n",
2073                    oldname, newname));
2074
2075         /* We have to allow the account name to end with a '$'.
2076            Also, follow the semantics in _samr_create_user() and lower case the
2077            posix name but preserve the case in passdb */
2078
2079         fstrcpy( oldname_lower, oldname );
2080         if (!strlower_m( oldname_lower )) {
2081                 return NT_STATUS_INVALID_PARAMETER;
2082         }
2083         fstrcpy( newname_lower, newname );
2084         if (!strlower_m( newname_lower )) {
2085                 return NT_STATUS_INVALID_PARAMETER;
2086         }
2087
2088         rename_script = realloc_string_sub2(rename_script,
2089                                         "%unew",
2090                                         newname_lower,
2091                                         true,
2092                                         true);
2093         if (!rename_script) {
2094                 return NT_STATUS_NO_MEMORY;
2095         }
2096         rename_script = realloc_string_sub2(rename_script,
2097                                         "%uold",
2098                                         oldname_lower,
2099                                         true,
2100                                         true);
2101         rc = smbrun(rename_script, NULL, NULL);
2102
2103         DEBUG(rc ? 0 : 3,("Running the command `%s' gave %d\n",
2104                           rename_script, rc));
2105
2106         TALLOC_FREE(rename_script);
2107
2108         if (rc == 0) {
2109                 smb_nscd_flush_user_cache();
2110         }
2111
2112         if (rc)
2113                 return NT_STATUS_UNSUCCESSFUL;
2114
2115         return NT_STATUS_OK;
2116 }
2117
2118 /**********************************************************************
2119  Add struct samu to LDAP.
2120 *********************************************************************/
2121
2122 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct samu * newpwd)
2123 {
2124         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2125         int rc;
2126         LDAPMessage     *result = NULL;
2127         LDAPMessage     *entry  = NULL;
2128         LDAPMod         **mods = NULL;
2129         int             ldap_op = LDAP_MOD_REPLACE;
2130         uint32_t                num_result;
2131         const char      **attr_list;
2132         char *escape_user = NULL;
2133         const char      *username = pdb_get_username(newpwd);
2134         const struct dom_sid    *sid = pdb_get_user_sid(newpwd);
2135         char *filter = NULL;
2136         char *dn = NULL;
2137         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2138         TALLOC_CTX *ctx = talloc_init("ldapsam_add_sam_account");
2139
2140         if (!ctx) {
2141                 return NT_STATUS_NO_MEMORY;
2142         }
2143
2144         if (!username || !*username) {
2145                 DEBUG(0, ("ldapsam_add_sam_account: Cannot add user without a username!\n"));
2146                 status = NT_STATUS_INVALID_PARAMETER;
2147                 goto fn_exit;
2148         }
2149
2150         /* free this list after the second search or in case we exit on failure */
2151         attr_list = get_userattr_list(ctx, ldap_state->schema_ver);
2152
2153         rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
2154
2155         if (rc != LDAP_SUCCESS) {
2156                 goto fn_exit;
2157         }
2158
2159         if (ldap_count_entries(smbldap_get_ldap(ldap_state->smbldap_state),
2160                                result) != 0) {
2161                 DEBUG(0,("ldapsam_add_sam_account: User '%s' already in the base, with samba attributes\n", 
2162                          username));
2163                 goto fn_exit;
2164         }
2165         ldap_msgfree(result);
2166         result = NULL;
2167
2168         if (pdb_element_is_set_or_changed(newpwd, PDB_USERSID)) {
2169                 rc = ldapsam_get_ldap_user_by_sid(ldap_state,
2170                                                   sid, &result);
2171                 if (rc == LDAP_SUCCESS) {
2172                         if (ldap_count_entries(
2173                                     smbldap_get_ldap(
2174                                             ldap_state->smbldap_state),
2175                                     result) != 0) {
2176                                 struct dom_sid_buf buf;
2177                                 DEBUG(0,("ldapsam_add_sam_account: SID '%s' "
2178                                          "already in the base, with samba "
2179                                          "attributes\n",
2180                                          dom_sid_str_buf(sid, &buf)));
2181                                 goto fn_exit;
2182                         }
2183                         ldap_msgfree(result);
2184                         result = NULL;
2185                 }
2186         }
2187
2188         /* does the entry already exist but without a samba attributes?
2189            we need to return the samba attributes here */
2190
2191         escape_user = escape_ldap_string(talloc_tos(), username);
2192         filter = talloc_strdup(attr_list, "(uid=%u)");
2193         if (!filter) {
2194                 status = NT_STATUS_NO_MEMORY;
2195                 goto fn_exit;
2196         }
2197         filter = talloc_all_string_sub(attr_list, filter, "%u", escape_user);
2198         TALLOC_FREE(escape_user);
2199         if (!filter) {
2200                 status = NT_STATUS_NO_MEMORY;
2201                 goto fn_exit;
2202         }
2203
2204         rc = smbldap_search_suffix(ldap_state->smbldap_state,
2205                                    filter, attr_list, &result);
2206         if ( rc != LDAP_SUCCESS ) {
2207                 goto fn_exit;
2208         }
2209
2210         num_result = ldap_count_entries(
2211                 smbldap_get_ldap(ldap_state->smbldap_state), result);
2212
2213         if (num_result > 1) {
2214                 DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
2215                 goto fn_exit;
2216         }
2217
2218         /* Check if we need to update an existing entry */
2219         if (num_result == 1) {
2220                 DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
2221                 ldap_op = LDAP_MOD_REPLACE;
2222                 entry = ldap_first_entry(
2223                         smbldap_get_ldap(ldap_state->smbldap_state), result);
2224                 dn = smbldap_talloc_dn(
2225                         ctx, smbldap_get_ldap(ldap_state->smbldap_state),
2226                         entry);
2227                 if (!dn) {
2228                         status = NT_STATUS_NO_MEMORY;
2229                         goto fn_exit;
2230                 }
2231
2232         } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) {
2233
2234                 struct dom_sid_buf buf;
2235
2236                 /* There might be a SID for this account already - say an idmap entry */
2237
2238                 filter = talloc_asprintf(ctx,
2239                                 "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))",
2240                                  get_userattr_key2string(ldap_state->schema_ver,
2241                                          LDAP_ATTR_USER_SID),
2242                                  dom_sid_str_buf(sid, &buf),
2243                                  LDAP_OBJ_IDMAP_ENTRY,
2244                                  LDAP_OBJ_SID_ENTRY);
2245                 if (!filter) {
2246                         status = NT_STATUS_NO_MEMORY;
2247                         goto fn_exit;
2248                 }
2249
2250                 /* free old result before doing a new search */
2251                 if (result != NULL) {
2252                         ldap_msgfree(result);
2253                         result = NULL;
2254                 }
2255                 rc = smbldap_search_suffix(ldap_state->smbldap_state,
2256                                            filter, attr_list, &result);
2257
2258                 if ( rc != LDAP_SUCCESS ) {
2259                         goto fn_exit;
2260                 }
2261
2262                 num_result = ldap_count_entries(
2263                         smbldap_get_ldap(ldap_state->smbldap_state), result);
2264
2265                 if (num_result > 1) {
2266                         DEBUG (0, ("ldapsam_add_sam_account: More than one user with specified Sid exists: bailing out!\n"));
2267                         goto fn_exit;
2268                 }
2269
2270                 /* Check if we need to update an existing entry */
2271                 if (num_result == 1) {
2272
2273                         DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
2274                         ldap_op = LDAP_MOD_REPLACE;
2275                         entry = ldap_first_entry (
2276                                 smbldap_get_ldap(ldap_state->smbldap_state),
2277                                 result);
2278                         dn = smbldap_talloc_dn (
2279                                 ctx,
2280                                 smbldap_get_ldap(ldap_state->smbldap_state),
2281                                 entry);
2282                         if (!dn) {
2283                                 status = NT_STATUS_NO_MEMORY;
2284                                 goto fn_exit;
2285                         }
2286                 }
2287         }
2288
2289         if (num_result == 0) {
2290                 char *escape_username;
2291                 /* Check if we need to add an entry */
2292                 DEBUG(3,("ldapsam_add_sam_account: Adding new user\n"));
2293                 ldap_op = LDAP_MOD_ADD;
2294
2295                 escape_username = escape_rdn_val_string_alloc(username);
2296                 if (!escape_username) {
2297                         status = NT_STATUS_NO_MEMORY;
2298                         goto fn_exit;
2299                 }
2300
2301                 if (username[strlen(username)-1] == '$') {
2302                         dn = talloc_asprintf(ctx,
2303                                         "uid=%s,%s",
2304                                         escape_username,
2305                                         lp_ldap_machine_suffix(talloc_tos()));
2306                 } else {
2307                         dn = talloc_asprintf(ctx,
2308                                         "uid=%s,%s",
2309                                         escape_username,
2310                                         lp_ldap_user_suffix(talloc_tos()));
2311                 }
2312
2313                 SAFE_FREE(escape_username);
2314                 if (!dn) {
2315                         status = NT_STATUS_NO_MEMORY;
2316                         goto fn_exit;
2317                 }
2318         }
2319
2320         if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2321                                 pdb_element_is_set_or_changed)) {
2322                 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2323                 if (mods != NULL) {
2324                         ldap_mods_free(mods, true);
2325                 }
2326                 goto fn_exit;
2327         }
2328
2329         if (mods == NULL) {
2330                 DEBUG(0,("ldapsam_add_sam_account: mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2331                 goto fn_exit;
2332         }
2333         switch ( ldap_state->schema_ver ) {
2334                 case SCHEMAVER_SAMBASAMACCOUNT:
2335                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT);
2336                         break;
2337                 default:
2338                         DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
2339                         break;
2340         }
2341
2342         status = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, pdb_element_is_set_or_changed);
2343         if (!NT_STATUS_IS_OK(status)) {
2344                 DEBUG(0,("ldapsam_add_sam_account: failed to modify/add user with uid = %s (dn = %s)\n",
2345                          pdb_get_username(newpwd),dn));
2346                 ldap_mods_free(mods, true);
2347                 goto fn_exit;
2348         }
2349
2350         DEBUG(2,("ldapsam_add_sam_account: added: uid == %s in the LDAP database\n", pdb_get_username(newpwd)));
2351         ldap_mods_free(mods, true);
2352
2353         status = NT_STATUS_OK;
2354
2355   fn_exit:
2356
2357         TALLOC_FREE(ctx);
2358         if (result) {
2359                 ldap_msgfree(result);
2360         }
2361         return status;
2362 }
2363
2364 /**********************************************************************
2365  *********************************************************************/
2366
2367 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2368                                      const char *filter,
2369                                      LDAPMessage ** result)
2370 {
2371         int scope = LDAP_SCOPE_SUBTREE;
2372         int rc;
2373         const char **attr_list;
2374
2375         attr_list = get_attr_list(NULL, groupmap_attr_list);
2376         rc = smbldap_search(ldap_state->smbldap_state,
2377                             lp_ldap_suffix(), scope,
2378                             filter, attr_list, 0, result);
2379         TALLOC_FREE(attr_list);
2380
2381         return rc;
2382 }
2383
2384 /**********************************************************************
2385  *********************************************************************/
2386
2387 static bool init_group_from_ldap(struct ldapsam_privates *ldap_state,
2388                                  GROUP_MAP *map, LDAPMessage *entry)
2389 {
2390         char *temp = NULL;
2391         TALLOC_CTX *ctx = talloc_init("init_group_from_ldap");
2392
2393         if (ldap_state == NULL || map == NULL || entry == NULL ||
2394             smbldap_get_ldap(ldap_state->smbldap_state) == NULL) {
2395                 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2396                 TALLOC_FREE(ctx);
2397                 return false;
2398         }
2399
2400         temp = smbldap_talloc_single_attribute(
2401                         smbldap_get_ldap(ldap_state->smbldap_state),
2402                         entry,
2403                         get_attr_key2string(groupmap_attr_list,
2404                                 LDAP_ATTR_GIDNUMBER),
2405                         ctx);
2406         if (!temp) {
2407                 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n", 
2408                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GIDNUMBER)));
2409                 TALLOC_FREE(ctx);
2410                 return false;
2411         }
2412         DEBUG(2, ("init_group_from_ldap: Entry found for group: %s\n", temp));
2413
2414         map->gid = (gid_t)atol(temp);
2415
2416         TALLOC_FREE(temp);
2417         temp = smbldap_talloc_single_attribute(
2418                         smbldap_get_ldap(ldap_state->smbldap_state),
2419                         entry,
2420                         get_attr_key2string(groupmap_attr_list,
2421                                 LDAP_ATTR_GROUP_SID),
2422                         ctx);
2423         if (!temp) {
2424                 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n",
2425                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID)));
2426                 TALLOC_FREE(ctx);
2427                 return false;
2428         }
2429
2430         if (!string_to_sid(&map->sid, temp)) {
2431                 DEBUG(1, ("SID string [%s] could not be read as a valid SID\n", temp));
2432                 TALLOC_FREE(ctx);
2433                 return false;
2434         }
2435
2436         TALLOC_FREE(temp);
2437         temp = smbldap_talloc_single_attribute(
2438                         smbldap_get_ldap(ldap_state->smbldap_state),
2439                         entry,
2440                         get_attr_key2string(groupmap_attr_list,
2441                                 LDAP_ATTR_GROUP_TYPE),
2442                         ctx);
2443         if (!temp) {
2444                 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n",
2445                         get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
2446                 TALLOC_FREE(ctx);
2447                 return false;
2448         }
2449         map->sid_name_use = (enum lsa_SidType)atol(temp);
2450
2451         if ((map->sid_name_use < SID_NAME_USER) ||
2452                         (map->sid_name_use > SID_NAME_UNKNOWN)) {
2453                 DEBUG(0, ("init_group_from_ldap: Unknown Group type: %d\n", map->sid_name_use));
2454                 TALLOC_FREE(ctx);
2455                 return false;
2456         }
2457
2458         TALLOC_FREE(temp);
2459         temp = smbldap_talloc_single_attribute(
2460                         smbldap_get_ldap(ldap_state->smbldap_state),
2461                         entry,
2462                         get_attr_key2string(groupmap_attr_list,
2463                                 LDAP_ATTR_DISPLAY_NAME),
2464                         ctx);
2465         if (!temp) {
2466                 temp = smbldap_talloc_single_attribute(
2467                                 smbldap_get_ldap(ldap_state->smbldap_state),
2468                                 entry,
2469                                 get_attr_key2string(groupmap_attr_list,
2470                                         LDAP_ATTR_CN),
2471                                 ctx);
2472                 if (!temp) {
2473                         DEBUG(0, ("init_group_from_ldap: Attributes cn not found either \
2474 for gidNumber(%lu)\n",(unsigned long)map->gid));
2475                         TALLOC_FREE(ctx);
2476                         return false;
2477                 }
2478         }
2479         map->nt_name = talloc_strdup(map, temp);
2480         if (!map->nt_name) {
2481                 TALLOC_FREE(ctx);
2482                 return false;
2483         }
2484
2485         TALLOC_FREE(temp);
2486         temp = smbldap_talloc_single_attribute(
2487                         smbldap_get_ldap(ldap_state->smbldap_state),
2488                         entry,
2489                         get_attr_key2string(groupmap_attr_list,
2490                                 LDAP_ATTR_DESC),
2491                         ctx);
2492         if (!temp) {
2493                 temp = talloc_strdup(ctx, "");
2494                 if (!temp) {
2495                         TALLOC_FREE(ctx);
2496                         return false;
2497                 }
2498         }
2499         map->comment = talloc_strdup(map, temp);
2500         if (!map->comment) {
2501                 TALLOC_FREE(ctx);
2502                 return false;
2503         }
2504
2505         if (lp_parm_bool(-1, "ldapsam", "trusted", false)) {
2506                 struct unixid id;
2507                 id.id = map->gid;
2508                 id.type = ID_TYPE_GID;
2509
2510                 idmap_cache_set_sid2unixid(&map->sid, &id);
2511         }
2512
2513         TALLOC_FREE(ctx);
2514         return true;
2515 }
2516
2517 /**********************************************************************
2518  *********************************************************************/
2519
2520 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2521                                  const char *filter,
2522                                  GROUP_MAP *map)
2523 {
2524         struct ldapsam_privates *ldap_state =
2525                 (struct ldapsam_privates *)methods->private_data;
2526         LDAPMessage *result = NULL;
2527         LDAPMessage *entry = NULL;
2528         int count;
2529
2530         if (ldapsam_search_one_group(ldap_state, filter, &result)
2531             != LDAP_SUCCESS) {
2532                 return NT_STATUS_NO_SUCH_GROUP;
2533         }
2534
2535         count = ldap_count_entries(priv2ld(ldap_state), result);
2536
2537         if (count < 1) {
2538                 DEBUG(4, ("ldapsam_getgroup: Did not find group, filter was "
2539                           "%s\n", filter));
2540                 ldap_msgfree(result);
2541                 return NT_STATUS_NO_SUCH_GROUP;
2542         }
2543
2544         if (count > 1) {
2545                 DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: "
2546                           "count=%d\n", filter, count));
2547                 ldap_msgfree(result);
2548                 return NT_STATUS_NO_SUCH_GROUP;
2549         }
2550
2551         entry = ldap_first_entry(priv2ld(ldap_state), result);
2552
2553         if (!entry) {
2554                 ldap_msgfree(result);
2555                 return NT_STATUS_UNSUCCESSFUL;
2556         }
2557
2558         if (!init_group_from_ldap(ldap_state, map, entry)) {
2559                 DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for "
2560                           "group filter %s\n", filter));
2561                 ldap_msgfree(result);
2562                 return NT_STATUS_NO_SUCH_GROUP;
2563         }
2564
2565         ldap_msgfree(result);
2566         return NT_STATUS_OK;
2567 }
2568
2569 /**********************************************************************
2570  *********************************************************************/
2571
2572 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2573                                  struct dom_sid sid)
2574 {
2575         char *filter = NULL;
2576         NTSTATUS status;
2577         struct dom_sid_buf tmp;
2578
2579         if (asprintf(&filter, "(&(objectClass=%s)(%s=%s))",
2580                 LDAP_OBJ_GROUPMAP,
2581                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID),
2582                 dom_sid_str_buf(&sid, &tmp)) < 0) {
2583                 return NT_STATUS_NO_MEMORY;
2584         }
2585
2586         status = ldapsam_getgroup(methods, filter, map);
2587         SAFE_FREE(filter);
2588         return status;
2589 }
2590
2591 /**********************************************************************
2592  *********************************************************************/
2593
2594 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2595                                  gid_t gid)
2596 {
2597         char *filter = NULL;
2598         NTSTATUS status;
2599
2600         if (asprintf(&filter, "(&(objectClass=%s)(%s=%lu))",
2601                 LDAP_OBJ_GROUPMAP,
2602                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
2603                 (unsigned long)gid) < 0) {
2604                 return NT_STATUS_NO_MEMORY;
2605         }
2606
2607         status = ldapsam_getgroup(methods, filter, map);
2608         SAFE_FREE(filter);
2609         return status;
2610 }
2611
2612 /**********************************************************************
2613  *********************************************************************/
2614
2615 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2616                                  const char *name)
2617 {
2618         char *filter = NULL;
2619         char *escape_name = escape_ldap_string(talloc_tos(), name);
2620         NTSTATUS status;
2621
2622         if (!escape_name) {
2623                 return NT_STATUS_NO_MEMORY;
2624         }
2625
2626         if (asprintf(&filter, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
2627                 LDAP_OBJ_GROUPMAP,
2628                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name,
2629                 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN),
2630                 escape_name) < 0) {
2631                 TALLOC_FREE(escape_name);
2632                 return NT_STATUS_NO_MEMORY;
2633         }
2634
2635         TALLOC_FREE(escape_name);
2636         status = ldapsam_getgroup(methods, filter, map);
2637         SAFE_FREE(filter);
2638         return status;
2639 }
2640
2641 static bool ldapsam_extract_rid_from_entry(LDAP *ldap_struct,
2642                                            LDAPMessage *entry,
2643                                            const struct dom_sid *domain_sid,
2644                                            uint32_t *rid)
2645 {
2646         fstring str;
2647         struct dom_sid sid;
2648
2649         if (!smbldap_get_single_attribute(ldap_struct, entry, "sambaSID",
2650                                           str, sizeof(str)-1)) {
2651                 DEBUG(10, ("Could not find sambaSID attribute\n"));
2652                 return False;
2653         }
2654
2655         if (!string_to_sid(&sid, str)) {
2656                 DEBUG(10, ("Could not convert string %s to sid\n", str));
2657                 return False;
2658         }
2659
2660         if (dom_sid_compare_domain(&sid, domain_sid) != 0) {
2661                 struct dom_sid_buf buf;
2662                 DEBUG(10, ("SID %s is not in expected domain %s\n",
2663                            str,
2664                            dom_sid_str_buf(domain_sid, &buf)));
2665                 return False;
2666         }
2667
2668         if (!sid_peek_rid(&sid, rid)) {
2669                 DEBUG(10, ("Could not peek into RID\n"));
2670                 return False;
2671         }
2672
2673         return True;
2674 }
2675
2676 static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
2677                                            TALLOC_CTX *mem_ctx,
2678                                            const struct dom_sid *group,
2679                                            uint32_t **pp_member_rids,
2680                                            size_t *p_num_members)
2681 {
2682         struct ldapsam_privates *ldap_state =
2683                 (struct ldapsam_privates *)methods->private_data;
2684         struct smbldap_state *conn = ldap_state->smbldap_state;
2685         const char *id_attrs[] = { "memberUid", "gidNumber", NULL };
2686         const char *sid_attrs[] = { "sambaSID", NULL };
2687         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2688         LDAPMessage *result = NULL;
2689         LDAPMessage *entry;
2690         char *filter;
2691         char **values = NULL;
2692         char **memberuid;
2693         char *gidstr;
2694         int rc, count;
2695         struct dom_sid_buf buf;
2696
2697         *pp_member_rids = NULL;
2698         *p_num_members = 0;
2699
2700         filter = talloc_asprintf(mem_ctx,
2701                                  "(&(objectClass=%s)"
2702                                  "(objectClass=%s)"
2703                                  "(sambaSID=%s))",
2704                                  LDAP_OBJ_POSIXGROUP,
2705                                  LDAP_OBJ_GROUPMAP,
2706                                  dom_sid_str_buf(group, &buf));
2707         if (filter == NULL) {
2708                 ret = NT_STATUS_NO_MEMORY;
2709                 goto done;
2710         }
2711
2712         rc = smbldap_search(conn, lp_ldap_suffix(),
2713                             LDAP_SCOPE_SUBTREE, filter, id_attrs, 0,
2714                             &result);
2715
2716         if (rc != LDAP_SUCCESS)
2717                 goto done;
2718
2719         smbldap_talloc_autofree_ldapmsg(mem_ctx, result);
2720
2721         count = ldap_count_entries(smbldap_get_ldap(conn), result);
2722
2723         if (count > 1) {
2724                 DEBUG(1, ("Found more than one groupmap entry for %s\n",
2725                           dom_sid_str_buf(group, &buf)));
2726                 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2727                 goto done;
2728         }
2729
2730         if (count == 0) {
2731                 ret = NT_STATUS_NO_SUCH_GROUP;
2732                 goto done;
2733         }
2734
2735         entry = ldap_first_entry(smbldap_get_ldap(conn), result);
2736         if (entry == NULL)
2737                 goto done;
2738
2739         gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx);
2740         if (!gidstr) {
2741                 DEBUG (0, ("ldapsam_enum_group_members: Unable to find the group's gid!\n"));
2742                 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2743                 goto done;
2744         }
2745
2746         values = ldap_get_values(smbldap_get_ldap(conn), entry, "memberUid");
2747
2748         if ((values != NULL) && (values[0] != NULL)) {
2749
2750                 filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(|", LDAP_OBJ_SAMBASAMACCOUNT);
2751                 if (filter == NULL) {
2752                         ret = NT_STATUS_NO_MEMORY;
2753                         goto done;
2754                 }
2755
2756                 for (memberuid = values; *memberuid != NULL; memberuid += 1) {
2757                         char *escape_memberuid;
2758
2759                         escape_memberuid = escape_ldap_string(talloc_tos(),
2760                                                               *memberuid);
2761                         if (escape_memberuid == NULL) {
2762                                 ret = NT_STATUS_NO_MEMORY;
2763                                 goto done;
2764                         }
2765
2766                         filter = talloc_asprintf_append_buffer(filter, "(uid=%s)", escape_memberuid);
2767                         TALLOC_FREE(escape_memberuid);
2768                         if (filter == NULL) {
2769                                 ret = NT_STATUS_NO_MEMORY;
2770                                 goto done;
2771                         }
2772                 }
2773
2774                 filter = talloc_asprintf_append_buffer(filter, "))");
2775                 if (filter == NULL) {
2776                         ret = NT_STATUS_NO_MEMORY;
2777                         goto done;
2778                 }
2779
2780                 rc = smbldap_search(conn, lp_ldap_suffix(),
2781                                     LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0,
2782                                     &result);
2783
2784                 if (rc != LDAP_SUCCESS)
2785                         goto done;
2786
2787                 count = ldap_count_entries(smbldap_get_ldap(conn), result);
2788                 DEBUG(10,("ldapsam_enum_group_members: found %d accounts\n", count));
2789
2790                 smbldap_talloc_autofree_ldapmsg(mem_ctx, result);
2791
2792                 for (entry = ldap_first_entry(smbldap_get_ldap(conn), result);
2793                      entry != NULL;
2794                      entry = ldap_next_entry(smbldap_get_ldap(conn), entry))
2795                 {
2796                         char *sidstr;
2797                         struct dom_sid sid;
2798                         uint32_t rid;
2799
2800                         sidstr = smbldap_talloc_single_attribute(
2801                                 smbldap_get_ldap(conn), entry, "sambaSID",
2802                                 mem_ctx);
2803                         if (!sidstr) {
2804                                 DEBUG(0, ("Severe DB error, %s can't miss the sambaSID"
2805                                           "attribute\n", LDAP_OBJ_SAMBASAMACCOUNT));
2806                                 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2807                                 goto done;
2808                         }
2809
2810                         if (!string_to_sid(&sid, sidstr))
2811                                 goto done;
2812
2813                         if (!sid_check_is_in_our_sam(&sid)) {
2814                                 DEBUG(0, ("Inconsistent SAM -- group member uid not "
2815                                           "in our domain\n"));
2816                                 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2817                                 goto done;
2818                         }
2819
2820                         sid_peek_rid(&sid, &rid);
2821
2822                         if (!add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
2823                                                 p_num_members)) {
2824                                 ret = NT_STATUS_NO_MEMORY;
2825                                 goto done;
2826                         }
2827                 }
2828         }
2829
2830         filter = talloc_asprintf(mem_ctx,
2831                                  "(&(objectClass=%s)"
2832                                  "(gidNumber=%s))",
2833                                  LDAP_OBJ_SAMBASAMACCOUNT,
2834                                  gidstr);
2835
2836         rc = smbldap_search(conn, lp_ldap_suffix(),
2837                             LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0,
2838                             &result);
2839
2840         if (rc != LDAP_SUCCESS)
2841                 goto done;
2842
2843         smbldap_talloc_autofree_ldapmsg(mem_ctx, result);
2844
2845         for (entry = ldap_first_entry(smbldap_get_ldap(conn), result);
2846              entry != NULL;
2847              entry = ldap_next_entry(smbldap_get_ldap(conn), entry))
2848         {
2849                 uint32_t rid;
2850
2851                 if (!ldapsam_extract_rid_from_entry(smbldap_get_ldap(conn),
2852                                                     entry,
2853                                                     get_global_sam_sid(),
2854                                                     &rid)) {
2855                         DEBUG(0, ("Severe DB error, %s can't miss the samba SID"                                                                "attribute\n", LDAP_OBJ_SAMBASAMACCOUNT));
2856                         ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2857                         goto done;
2858                 }
2859
2860                 if (!add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
2861                                         p_num_members)) {
2862                         ret = NT_STATUS_NO_MEMORY;
2863                         goto done;
2864                 }
2865         }
2866
2867         ret = NT_STATUS_OK;
2868
2869  done:
2870
2871         if (values)
2872                 ldap_value_free(values);
2873
2874         return ret;
2875 }
2876
2877 static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
2878                                                TALLOC_CTX *mem_ctx,
2879                                                struct samu *user,
2880                                                struct dom_sid **pp_sids,
2881                                                gid_t **pp_gids,
2882                                                uint32_t *p_num_groups)
2883 {
2884         struct ldapsam_privates *ldap_state =
2885                 (struct ldapsam_privates *)methods->private_data;
2886         struct smbldap_state *conn = ldap_state->smbldap_state;
2887         char *filter;
2888         const char *attrs[] = { "gidNumber", "sambaSID", NULL };
2889         char *escape_name;
2890         int rc, count;
2891         LDAPMessage *result = NULL;
2892         LDAPMessage *entry;
2893         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2894         uint32_t num_sids;
2895         uint32_t num_gids;
2896         char *gidstr;
2897         gid_t primary_gid = -1;
2898         int error = 0;
2899
2900         *pp_sids = NULL;
2901         num_sids = 0;
2902
2903         if (pdb_get_username(user) == NULL) {
2904                 return NT_STATUS_INVALID_PARAMETER;
2905         }
2906
2907         escape_name = escape_ldap_string(talloc_tos(), pdb_get_username(user));
2908         if (escape_name == NULL)
2909                 return NT_STATUS_NO_MEMORY;
2910
2911         if (user->unix_pw) {
2912                 primary_gid = user->unix_pw->pw_gid;
2913         } else {
2914                 /* retrieve the users primary gid */
2915                 filter = talloc_asprintf(mem_ctx,
2916                                          "(&(objectClass=%s)(uid=%s))",
2917                                          LDAP_OBJ_SAMBASAMACCOUNT,
2918                                          escape_name);
2919                 if (filter == NULL) {
2920                         ret = NT_STATUS_NO_MEMORY;
2921                         goto done;
2922                 }
2923
2924                 rc = smbldap_search(conn, lp_ldap_suffix(),
2925                                     LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
2926
2927                 if (rc != LDAP_SUCCESS)
2928                         goto done;
2929
2930                 smbldap_talloc_autofree_ldapmsg(mem_ctx, result);
2931
2932                 count = ldap_count_entries(priv2ld(ldap_state), result);
2933
2934                 switch (count) {
2935                 case 0:
2936                         DEBUG(1, ("User account [%s] not found!\n", pdb_get_username(user)));
2937                         ret = NT_STATUS_NO_SUCH_USER;
2938                         goto done;
2939                 case 1:
2940                         entry = ldap_first_entry(priv2ld(ldap_state), result);
2941
2942                         gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx);
2943                         if (!gidstr) {
2944                                 DEBUG (1, ("Unable to find the member's gid!\n"));
2945                                 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2946                                 goto done;
2947                         }
2948                         primary_gid = smb_strtoul(gidstr,
2949                                                   NULL,
2950                                                   10,
2951                                                   &error,
2952                                                   SMB_STR_STANDARD);
2953                         if (error != 0) {
2954                                 DBG_ERR("Failed to convert GID\n");
2955                                 goto done;
2956                         }
2957                         break;
2958                 default:
2959                         DEBUG(1, ("found more than one account with the same user name ?!\n"));
2960                         ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2961                         goto done;
2962                 }
2963         }
2964
2965         filter = talloc_asprintf(mem_ctx,
2966                                  "(&(objectClass=%s)(|(memberUid=%s)(gidNumber=%u)))",
2967                                  LDAP_OBJ_POSIXGROUP, escape_name, (unsigned int)primary_gid);
2968         if (filter == NULL) {
2969                 ret = NT_STATUS_NO_MEMORY;
2970                 goto done;
2971         }
2972
2973         rc = smbldap_search(conn, lp_ldap_suffix(),
2974                             LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
2975
2976         if (rc != LDAP_SUCCESS)
2977                 goto done;
2978
2979         smbldap_talloc_autofree_ldapmsg(mem_ctx, result);
2980
2981         num_gids = 0;
2982         *pp_gids = NULL;
2983
2984         num_sids = 0;
2985         *pp_sids = NULL;
2986
2987         /* We need to add the primary group as the first gid/sid */
2988
2989         if (!add_gid_to_array_unique(mem_ctx, primary_gid, pp_gids, &num_gids)) {
2990                 ret = NT_STATUS_NO_MEMORY;
2991                 goto done;
2992         }
2993
2994         /* This sid will be replaced later */
2995
2996         ret = add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids,
2997                                       &num_sids);
2998         if (!NT_STATUS_IS_OK(ret)) {
2999                 goto done;
3000         }
3001
3002         for (entry = ldap_first_entry(smbldap_get_ldap(conn), result);
3003              entry != NULL;
3004              entry = ldap_next_entry(smbldap_get_ldap(conn), entry))
3005         {
3006                 fstring str;
3007                 struct dom_sid sid;
3008                 gid_t gid;
3009
3010                 if (!smbldap_get_single_attribute(smbldap_get_ldap(conn),
3011                                                   entry, "sambaSID",
3012                                                   str, sizeof(str)-1))
3013                         continue;
3014
3015                 if (!string_to_sid(&sid, str))
3016                         goto done;
3017
3018                 if (!smbldap_get_single_attribute(smbldap_get_ldap(conn),
3019                                                   entry, "gidNumber",
3020                                                   str, sizeof(str)-1))
3021                         continue;
3022
3023                 gid = smb_strtoul(str, NULL, 10, &error, SMB_STR_FULL_STR_CONV);
3024
3025                 if (error != 0) {
3026                         goto done;
3027                 }
3028
3029                 if (gid == primary_gid) {
3030                         sid_copy(&(*pp_sids)[0], &sid);
3031                 } else {
3032                         if (!add_gid_to_array_unique(mem_ctx, gid, pp_gids,
3033                                                 &num_gids)) {
3034                                 ret = NT_STATUS_NO_MEMORY;
3035                                 goto done;
3036                         }
3037                         ret = add_sid_to_array_unique(mem_ctx, &sid, pp_sids,
3038                                                       &num_sids);
3039                         if (!NT_STATUS_IS_OK(ret)) {
3040                                 goto done;
3041                         }
3042                 }
3043         }
3044
3045         if (dom_sid_compare(&global_sid_NULL, &(*pp_sids)[0]) == 0) {
3046                 DEBUG(3, ("primary group of [%s] not found\n",
3047                           pdb_get_username(user)));
3048                 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
3049                 goto done;
3050         }
3051
3052         *p_num_groups = num_sids;
3053
3054         ret = NT_STATUS_OK;
3055
3056  done:
3057
3058         TALLOC_FREE(escape_name);
3059         return ret;
3060 }
3061
3062 /**********************************************************************
3063  * Augment a posixGroup object with a sambaGroupMapping domgroup
3064  *********************************************************************/
3065
3066 static NTSTATUS ldapsam_map_posixgroup(TALLOC_CTX *mem_ctx,
3067                                        struct ldapsam_privates *ldap_state,
3068                                        GROUP_MAP *map)
3069 {
3070         const char *filter, *dn;
3071         LDAPMessage *msg, *entry;
3072         LDAPMod **mods;
3073         struct dom_sid_buf buf;
3074         int rc;
3075
3076         filter = talloc_asprintf(mem_ctx,
3077                                  "(&(objectClass=%s)(gidNumber=%u))",
3078                                  LDAP_OBJ_POSIXGROUP, (unsigned int)map->gid);
3079         if (filter == NULL) {
3080                 return NT_STATUS_NO_MEMORY;
3081         }
3082
3083         rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
3084                                    get_attr_list(mem_ctx, groupmap_attr_list),
3085                                    &msg);
3086         smbldap_talloc_autofree_ldapmsg(mem_ctx, msg);
3087
3088         if ((rc != LDAP_SUCCESS) ||
3089             (ldap_count_entries(smbldap_get_ldap(ldap_state->smbldap_state),
3090                                 msg) != 1) ||
3091             ((entry = ldap_first_entry(
3092                       smbldap_get_ldap(ldap_state->smbldap_state),
3093                       msg)) == NULL)) {
3094                 return NT_STATUS_NO_SUCH_GROUP;
3095         }
3096
3097         dn = smbldap_talloc_dn(mem_ctx,
3098                                smbldap_get_ldap(ldap_state->smbldap_state),
3099                                entry);
3100         if (dn == NULL) {
3101                 return NT_STATUS_NO_MEMORY;
3102         }
3103
3104         mods = NULL;
3105         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass",
3106                         LDAP_OBJ_GROUPMAP);
3107         smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state), entry,
3108                          &mods, "sambaSid",
3109                          dom_sid_str_buf(&map->sid, &buf));
3110         smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state), entry,
3111                          &mods, "sambaGroupType",
3112                          talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
3113         smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state), entry,
3114                          &mods, "displayName",
3115                          map->nt_name);
3116         smbldap_make_mod(smbldap_get_ldap(ldap_state->smbldap_state), entry,
3117                          &mods, "description",
3118                          map->comment);
3119         smbldap_talloc_autofree_ldapmod(mem_ctx, mods);
3120
3121         rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
3122         if (rc != LDAP_SUCCESS) {
3123                 return NT_STATUS_ACCESS_DENIED;
3124         }
3125
3126         return NT_STATUS_OK;
3127 }
3128
3129 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
3130                                                 GROUP_MAP *map)
3131 {
3132         struct ldapsam_privates *ldap_state =
3133                 (struct ldapsam_privates *)methods->private_data;
3134         LDAPMessage *msg = NULL;
3135         LDAPMod **mods = NULL;
3136         const char *attrs[] = { NULL };
3137         char *filter;
3138
3139         char *dn;
3140         TALLOC_CTX *mem_ctx;
3141         NTSTATUS result;
3142
3143         struct dom_sid sid;
3144         struct dom_sid_buf buf;
3145         struct unixid id;
3146
3147         int rc;
3148
3149         mem_ctx = talloc_new(NULL);
3150         if (mem_ctx == NULL) {
3151                 DEBUG(0, ("talloc_new failed\n"));