1/*
2   Unix SMB/CIFS implementation.
3
4   Winbind ADS backend functions
5
6   Copyright (C) Andrew Tridgell 2001
7   Copyright (C) Andrew Bartlett 2002
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24#include "includes.h"
25#ifdef HAVE_LDAP
26
27/* convert a single name to a sid in a domain */
28NTSTATUS ads_name_to_sid(ADS_STRUCT *ads,
29			 const char *name,
30			 DOM_SID *sid,
31			 enum SID_NAME_USE *type)
32{
33	const char *attrs[] = {"objectSid", "sAMAccountType", NULL};
34	int count;
35	ADS_STATUS rc;
36	void *res = NULL;
37	char *ldap_exp;
38	uint32 t;
39	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
40	char *escaped_name = escape_ldap_string_alloc(name);
41	char *escaped_realm = escape_ldap_string_alloc(ads->config.realm);
42
43	if (!escaped_name || !escaped_realm) {
44		status = NT_STATUS_NO_MEMORY;
45		goto done;
46	}
47
48	if (asprintf(&ldap_exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))",
49		     escaped_name, escaped_name, escaped_realm) == -1) {
50		DEBUG(1,("ads_name_to_sid: asprintf failed!\n"));
51		status = NT_STATUS_NO_MEMORY;
52		goto done;
53	}
54
55	rc = ads_search_retry(ads, &res, ldap_exp, attrs);
56	free(ldap_exp);
57	if (!ADS_ERR_OK(rc)) {
58		DEBUG(1,("name_to_sid ads_search: %s\n", ads_errstr(rc)));
59		goto done;
60	}
61
62	count = ads_count_replies(ads, res);
63	if (count != 1) {
64		DEBUG(1,("name_to_sid: %s not found\n", name));
65		goto done;
66	}
67
68	if (!ads_pull_sid(ads, res, "objectSid", sid)) {
69		DEBUG(1,("No sid for %s !?\n", name));
70		goto done;
71	}
72
73	if (!ads_pull_uint32(ads, res, "sAMAccountType", &t)) {
74		DEBUG(1,("No sAMAccountType for %s !?\n", name));
75		goto done;
76	}
77
78	*type = ads_atype_map(t);
79
80	status = NT_STATUS_OK;
81
82	DEBUG(3,("ads name_to_sid mapped %s\n", name));
83
84done:
85	if (res) ads_msgfree(ads, res);
86
87	SAFE_FREE(escaped_name);
88	SAFE_FREE(escaped_realm);
89
90	return status;
91}
92
93/* convert a sid to a user or group name */
94NTSTATUS ads_sid_to_name(ADS_STRUCT *ads,
95			 TALLOC_CTX *mem_ctx,
96			 const DOM_SID *sid,
97			 char **name,
98			 enum SID_NAME_USE *type)
99{
100	const char *attrs[] = {"userPrincipalName",
101			       "sAMAccountName",
102			       "sAMAccountType", NULL};
103	ADS_STATUS rc;
104	void *msg = NULL;
105	char *ldap_exp = NULL;
106	char *sidstr = NULL;
107	uint32 atype;
108	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
109
110	if (!(sidstr = sid_binstring(sid))) {
111		DEBUG(1,("ads_sid_to_name: sid_binstring failed!\n"));
112		status = NT_STATUS_NO_MEMORY;
113		goto done;
114	}
115
116	if (asprintf(&ldap_exp, "(objectSid=%s)", sidstr) == -1) {
117		DEBUG(1,("ads_sid_to_name: asprintf failed!\n"));
118		status = NT_STATUS_NO_MEMORY;
119		goto done;
120	}
121
122	rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
123	if (!ADS_ERR_OK(rc)) {
124		status = ads_ntstatus(rc);
125		DEBUG(1,("ads_sid_to_name ads_search: %s\n", ads_errstr(rc)));
126		goto done;
127	}
128
129	if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) {
130		goto done;
131	}
132
133	*name = ads_pull_username(ads, mem_ctx, msg);
134	if (!*name) {
135		DEBUG(1,("ads_sid_to_name: ads_pull_username retuned NULL!\n"));
136		status = NT_STATUS_NO_MEMORY;
137		goto done;
138	}
139
140	*type = ads_atype_map(atype);
141
142	status = NT_STATUS_OK;
143
144	DEBUG(3,("ads sid_to_name mapped %s\n", *name));
145
146done:
147	if (msg) ads_msgfree(ads, msg);
148
149	SAFE_FREE(ldap_exp);
150	SAFE_FREE(sidstr);
151
152	return status;
153}
154
155
156/* convert a sid to a DN */
157
158ADS_STATUS ads_sid_to_dn(ADS_STRUCT *ads,
159			 TALLOC_CTX *mem_ctx,
160			 const DOM_SID *sid,
161			 char **dn)
162{
163	ADS_STATUS rc;
164	LDAPMessage *msg = NULL;
165	LDAPMessage *entry = NULL;
166	char *ldap_exp;
167	char *sidstr = NULL;
168	int count;
169	char *dn2 = NULL;
170
171	const char *attr[] = {
172		"dn",
173		NULL
174	};
175
176	if (!(sidstr = sid_binstring(sid))) {
177		DEBUG(1,("ads_sid_to_dn: sid_binstring failed!\n"));
178		rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
179		goto done;
180	}
181
182	if(!(ldap_exp = talloc_asprintf(mem_ctx, "(objectSid=%s)", sidstr))) {
183		DEBUG(1,("ads_sid_to_dn: talloc_asprintf failed!\n"));
184		rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
185		goto done;
186	}
187
188	rc = ads_search_retry(ads, (void **)&msg, ldap_exp, attr);
189
190	if (!ADS_ERR_OK(rc)) {
191		DEBUG(1,("ads_sid_to_dn ads_search: %s\n", ads_errstr(rc)));
192		goto done;
193	}
194
195	if ((count = ads_count_replies(ads, msg)) != 1) {
196		fstring sid_string;
197		DEBUG(1,("ads_sid_to_dn (sid=%s): Not found (count=%d)\n",
198			 sid_to_string(sid_string, sid), count));
199		rc = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
200		goto done;
201	}
202
203	entry = ads_first_entry(ads, msg);
204
205	dn2 = ads_get_dn(ads, entry);
206
207	if (!dn2) {
208		rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
209		goto done;
210	}
211
212	*dn = talloc_strdup(mem_ctx, dn2);
213
214	if (!*dn) {
215		ads_memfree(ads, dn2);
216		rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
217		goto done;
218	}
219
220	rc = ADS_ERROR_NT(NT_STATUS_OK);
221
222	DEBUG(3,("ads sid_to_dn mapped %s\n", dn2));
223
224	SAFE_FREE(dn2);
225done:
226	if (msg) ads_msgfree(ads, msg);
227	if (dn2) ads_memfree(ads, dn2);
228
229	SAFE_FREE(sidstr);
230
231	return rc;
232}
233
234#endif
235