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