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