s3: libsmb: In cli_list_old_send(), push state->mask into the packet, not just mask.
[Samba.git] / source3 / winbindd / idmap_ad_nss.c
blob31202806214626b46d0c7893f99c95913a9df42f
1 /*
2 * idmap_ad: map between Active Directory and RFC 2307 or "Services for Unix" (SFU) Accounts
4 * Unix SMB/CIFS implementation.
6 * Winbind ADS backend functions
8 * Copyright (C) Andrew Tridgell 2001
9 * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
10 * Copyright (C) Gerald (Jerry) Carter 2004-2007
11 * Copyright (C) Luke Howard 2001-2004
12 * Copyright (C) Michael Adam 2008,2010
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see <http://www.gnu.org/licenses/>.
28 #include "includes.h"
29 #include "winbindd.h"
30 #include "../libds/common/flags.h"
31 #include "winbindd_ads.h"
32 #include "libads/ldap_schema.h"
33 #include "nss_info.h"
34 #include "idmap.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "../libcli/security/security.h"
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_IDMAP
41 #define CHECK_ALLOC_DONE(mem) do { \
42 if (!mem) { \
43 DEBUG(0, ("Out of memory!\n")); \
44 ret = NT_STATUS_NO_MEMORY; \
45 goto done; \
46 } \
47 } while (0)
49 struct idmap_ad_context {
50 ADS_STRUCT *ads;
51 struct posix_schema *ad_schema;
52 enum wb_posix_mapping ad_map_type; /* WB_POSIX_MAP_UNKNOWN */
55 /************************************************************************
56 ***********************************************************************/
58 static ADS_STATUS ad_idmap_cached_connection(struct idmap_domain *dom)
60 ADS_STATUS status;
61 struct idmap_ad_context * ctx;
63 DEBUG(10, ("ad_idmap_cached_connection: called for domain '%s'\n",
64 dom->name));
66 ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
68 status = ads_idmap_cached_connection(dom->name, ctx, &ctx->ads);
69 if (!ADS_ERR_OK(status)) {
70 return status;
73 /* if we have a valid ADS_STRUCT and the schema model is
74 defined, then we can return here. */
76 if ( ctx->ad_schema ) {
77 return ADS_SUCCESS;
80 /* Otherwise, set the schema model */
82 if ( (ctx->ad_map_type == WB_POSIX_MAP_SFU) ||
83 (ctx->ad_map_type == WB_POSIX_MAP_SFU20) ||
84 (ctx->ad_map_type == WB_POSIX_MAP_RFC2307) )
86 status = ads_check_posix_schema_mapping(
87 ctx, ctx->ads, ctx->ad_map_type, &ctx->ad_schema);
88 if ( !ADS_ERR_OK(status) ) {
89 DEBUG(2,("ad_idmap_cached_connection: Failed to obtain schema details!\n"));
93 return status;
97 * nss_info_{sfu,sfu20,rfc2307}
100 /************************************************************************
101 Initialize the {sfu,sfu20,rfc2307} state
102 ***********************************************************************/
104 static const char *wb_posix_map_unknown_string = "WB_POSIX_MAP_UNKNOWN";
105 static const char *wb_posix_map_template_string = "WB_POSIX_MAP_TEMPLATE";
106 static const char *wb_posix_map_sfu_string = "WB_POSIX_MAP_SFU";
107 static const char *wb_posix_map_sfu20_string = "WB_POSIX_MAP_SFU20";
108 static const char *wb_posix_map_rfc2307_string = "WB_POSIX_MAP_RFC2307";
109 static const char *wb_posix_map_unixinfo_string = "WB_POSIX_MAP_UNIXINFO";
111 static const char *ad_map_type_string(enum wb_posix_mapping map_type)
113 switch (map_type) {
114 case WB_POSIX_MAP_TEMPLATE:
115 return wb_posix_map_template_string;
116 case WB_POSIX_MAP_SFU:
117 return wb_posix_map_sfu_string;
118 case WB_POSIX_MAP_SFU20:
119 return wb_posix_map_sfu20_string;
120 case WB_POSIX_MAP_RFC2307:
121 return wb_posix_map_rfc2307_string;
122 case WB_POSIX_MAP_UNIXINFO:
123 return wb_posix_map_unixinfo_string;
124 default:
125 return wb_posix_map_unknown_string;
129 static NTSTATUS nss_ad_generic_init(struct nss_domain_entry *e,
130 enum wb_posix_mapping new_ad_map_type)
132 struct idmap_domain *dom;
133 struct idmap_ad_context *ctx;
135 if (e->state != NULL) {
136 dom = talloc_get_type(e->state, struct idmap_domain);
137 } else {
138 dom = talloc_zero(e, struct idmap_domain);
139 if (dom == NULL) {
140 DEBUG(0, ("Out of memory!\n"));
141 return NT_STATUS_NO_MEMORY;
143 e->state = dom;
146 if (e->domain != NULL) {
147 dom->name = talloc_strdup(dom, e->domain);
148 if (dom->name == NULL) {
149 DEBUG(0, ("Out of memory!\n"));
150 return NT_STATUS_NO_MEMORY;
154 if (dom->private_data != NULL) {
155 ctx = talloc_get_type(dom->private_data,
156 struct idmap_ad_context);
157 } else {
158 ctx = talloc_zero(dom, struct idmap_ad_context);
159 if (ctx == NULL) {
160 DEBUG(0, ("Out of memory!\n"));
161 return NT_STATUS_NO_MEMORY;
163 ctx->ad_map_type = WB_POSIX_MAP_RFC2307;
164 dom->private_data = ctx;
167 if ((ctx->ad_map_type != WB_POSIX_MAP_UNKNOWN) &&
168 (ctx->ad_map_type != new_ad_map_type))
170 DEBUG(2, ("nss_ad_generic_init: "
171 "Warning: overriding previously set posix map type "
172 "%s for domain %s with map type %s.\n",
173 ad_map_type_string(ctx->ad_map_type),
174 dom->name,
175 ad_map_type_string(new_ad_map_type)));
178 ctx->ad_map_type = new_ad_map_type;
180 return NT_STATUS_OK;
183 static NTSTATUS nss_sfu_init( struct nss_domain_entry *e )
185 return nss_ad_generic_init(e, WB_POSIX_MAP_SFU);
188 static NTSTATUS nss_sfu20_init( struct nss_domain_entry *e )
190 return nss_ad_generic_init(e, WB_POSIX_MAP_SFU20);
193 static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e )
195 return nss_ad_generic_init(e, WB_POSIX_MAP_RFC2307);
198 /**********************************************************************
199 *********************************************************************/
201 static NTSTATUS nss_ad_map_to_alias(TALLOC_CTX *mem_ctx,
202 struct nss_domain_entry *e,
203 const char *name,
204 char **alias)
206 const char *attrs[] = {NULL, /* attr_uid */
207 NULL };
208 char *filter = NULL;
209 LDAPMessage *msg = NULL;
210 ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
211 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
212 struct idmap_domain *dom;
213 struct idmap_ad_context *ctx = NULL;
215 /* Check incoming parameters */
217 if ( !e || !e->domain || !name || !*alias) {
218 nt_status = NT_STATUS_INVALID_PARAMETER;
219 goto done;
222 /* Only do query if we are online */
224 if (idmap_is_offline()) {
225 nt_status = NT_STATUS_FILE_IS_OFFLINE;
226 goto done;
229 dom = talloc_get_type(e->state, struct idmap_domain);
230 ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
232 ads_status = ad_idmap_cached_connection(dom);
233 if (!ADS_ERR_OK(ads_status)) {
234 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
237 if (!ctx->ad_schema) {
238 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
239 goto done;
242 attrs[0] = ctx->ad_schema->posix_uid_attr;
244 filter = talloc_asprintf(mem_ctx,
245 "(sAMAccountName=%s)",
246 name);
247 if (!filter) {
248 nt_status = NT_STATUS_NO_MEMORY;
249 goto done;
252 ads_status = ads_search_retry(ctx->ads, &msg, filter, attrs);
253 if (!ADS_ERR_OK(ads_status)) {
254 nt_status = ads_ntstatus(ads_status);
255 goto done;
258 *alias = ads_pull_string(ctx->ads, mem_ctx, msg, ctx->ad_schema->posix_uid_attr);
260 if (!*alias) {
261 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
264 nt_status = NT_STATUS_OK;
266 done:
267 if (filter) {
268 talloc_destroy(filter);
270 if (msg) {
271 ads_msgfree(ctx->ads, msg);
274 return nt_status;
277 /**********************************************************************
278 *********************************************************************/
280 static NTSTATUS nss_ad_map_from_alias( TALLOC_CTX *mem_ctx,
281 struct nss_domain_entry *e,
282 const char *alias,
283 char **name )
285 const char *attrs[] = {"sAMAccountName",
286 NULL };
287 char *filter = NULL;
288 LDAPMessage *msg = NULL;
289 ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
290 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
291 char *username = NULL;
292 struct idmap_domain *dom;
293 struct idmap_ad_context *ctx = NULL;
295 /* Check incoming parameters */
297 if ( !alias || !name) {
298 nt_status = NT_STATUS_INVALID_PARAMETER;
299 goto done;
302 /* Only do query if we are online */
304 if (idmap_is_offline()) {
305 nt_status = NT_STATUS_FILE_IS_OFFLINE;
306 goto done;
309 dom = talloc_get_type(e->state, struct idmap_domain);
310 ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
312 ads_status = ad_idmap_cached_connection(dom);
313 if (!ADS_ERR_OK(ads_status)) {
314 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
317 if (!ctx->ad_schema) {
318 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
319 goto done;
322 filter = talloc_asprintf(mem_ctx,
323 "(%s=%s)",
324 ctx->ad_schema->posix_uid_attr,
325 alias);
326 if (!filter) {
327 nt_status = NT_STATUS_NO_MEMORY;
328 goto done;
331 ads_status = ads_search_retry(ctx->ads, &msg, filter, attrs);
332 if (!ADS_ERR_OK(ads_status)) {
333 nt_status = ads_ntstatus(ads_status);
334 goto done;
337 username = ads_pull_string(ctx->ads, mem_ctx, msg,
338 "sAMAccountName");
339 if (!username) {
340 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
341 goto done;
344 *name = talloc_asprintf(mem_ctx, "%s\\%s",
345 lp_workgroup(),
346 username);
347 if (!*name) {
348 nt_status = NT_STATUS_NO_MEMORY;
349 goto done;
352 nt_status = NT_STATUS_OK;
354 done:
355 TALLOC_FREE(username);
356 TALLOC_FREE(filter);
357 if (msg) {
358 ads_msgfree(ctx->ads, msg);
361 return nt_status;
364 /************************************************************************
365 Function dispatch tables for the idmap and nss plugins
366 ***********************************************************************/
368 /* The SFU and RFC2307 NSS plugins share everything but the init
369 function which sets the intended schema model to use */
371 static const struct nss_info_methods nss_rfc2307_methods = {
372 .init = nss_rfc2307_init,
373 .map_to_alias = nss_ad_map_to_alias,
374 .map_from_alias = nss_ad_map_from_alias,
377 static const struct nss_info_methods nss_sfu_methods = {
378 .init = nss_sfu_init,
379 .map_to_alias = nss_ad_map_to_alias,
380 .map_from_alias = nss_ad_map_from_alias,
383 static const struct nss_info_methods nss_sfu20_methods = {
384 .init = nss_sfu20_init,
385 .map_to_alias = nss_ad_map_to_alias,
386 .map_from_alias = nss_ad_map_from_alias,
391 /************************************************************************
392 Initialize the plugins
393 ***********************************************************************/
395 NTSTATUS idmap_ad_nss_init(TALLOC_CTX *mem_ctx)
397 NTSTATUS status;
399 status = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
400 "rfc2307", &nss_rfc2307_methods);
401 if (!NT_STATUS_IS_OK(status)) {
402 return status;
405 status = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
406 "sfu", &nss_sfu_methods);
407 if (!NT_STATUS_IS_OK(status)) {
408 return status;
411 status = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
412 "sfu20", &nss_sfu20_methods);
413 if (!NT_STATUS_IS_OK(status)) {
414 return status;
417 return NT_STATUS_OK;