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