From: Volker Lendecke Date: Tue, 29 Mar 2016 14:03:04 +0000 (+0200) Subject: idmap_ad: Separate out the nss functions X-Git-Tag: talloc-2.1.7~240 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=154570d9e9067ea419ddd5eb6920964a0935711e;p=thirdparty%2Fsamba.git idmap_ad: Separate out the nss functions The nss functions technically right now are part of the idmap modules. However, there is no intrinsic reason for this mixture of concerns. I would like to heavily modify the idmap_ad idmapping functions without modifying the nss functions (yet!!). So as a first step this patch moves the nss functions textually out of the way. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index e5dea208436..8f15ecb5433 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -561,377 +561,6 @@ done: return ret; } -/* - * nss_info_{sfu,sfu20,rfc2307} - */ - -/************************************************************************ - Initialize the {sfu,sfu20,rfc2307} state - ***********************************************************************/ - -static const char *wb_posix_map_unknown_string = "WB_POSIX_MAP_UNKNOWN"; -static const char *wb_posix_map_template_string = "WB_POSIX_MAP_TEMPLATE"; -static const char *wb_posix_map_sfu_string = "WB_POSIX_MAP_SFU"; -static const char *wb_posix_map_sfu20_string = "WB_POSIX_MAP_SFU20"; -static const char *wb_posix_map_rfc2307_string = "WB_POSIX_MAP_RFC2307"; -static const char *wb_posix_map_unixinfo_string = "WB_POSIX_MAP_UNIXINFO"; - -static const char *ad_map_type_string(enum wb_posix_mapping map_type) -{ - switch (map_type) { - case WB_POSIX_MAP_TEMPLATE: - return wb_posix_map_template_string; - case WB_POSIX_MAP_SFU: - return wb_posix_map_sfu_string; - case WB_POSIX_MAP_SFU20: - return wb_posix_map_sfu20_string; - case WB_POSIX_MAP_RFC2307: - return wb_posix_map_rfc2307_string; - case WB_POSIX_MAP_UNIXINFO: - return wb_posix_map_unixinfo_string; - default: - return wb_posix_map_unknown_string; - } -} - -static NTSTATUS nss_ad_generic_init(struct nss_domain_entry *e, - enum wb_posix_mapping new_ad_map_type) -{ - struct idmap_domain *dom; - struct idmap_ad_context *ctx; - - if (e->state != NULL) { - dom = talloc_get_type(e->state, struct idmap_domain); - } else { - dom = talloc_zero(e, struct idmap_domain); - if (dom == NULL) { - DEBUG(0, ("Out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - e->state = dom; - } - - if (e->domain != NULL) { - dom->name = talloc_strdup(dom, e->domain); - if (dom->name == NULL) { - DEBUG(0, ("Out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - } - - if (dom->private_data != NULL) { - ctx = talloc_get_type(dom->private_data, - struct idmap_ad_context); - } else { - ctx = talloc_zero(dom, struct idmap_ad_context); - if (ctx == NULL) { - DEBUG(0, ("Out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - ctx->ad_map_type = WB_POSIX_MAP_RFC2307; - dom->private_data = ctx; - } - - if ((ctx->ad_map_type != WB_POSIX_MAP_UNKNOWN) && - (ctx->ad_map_type != new_ad_map_type)) - { - DEBUG(2, ("nss_ad_generic_init: " - "Warning: overriding previously set posix map type " - "%s for domain %s with map type %s.\n", - ad_map_type_string(ctx->ad_map_type), - dom->name, - ad_map_type_string(new_ad_map_type))); - } - - ctx->ad_map_type = new_ad_map_type; - - return NT_STATUS_OK; -} - -static NTSTATUS nss_sfu_init( struct nss_domain_entry *e ) -{ - return nss_ad_generic_init(e, WB_POSIX_MAP_SFU); -} - -static NTSTATUS nss_sfu20_init( struct nss_domain_entry *e ) -{ - return nss_ad_generic_init(e, WB_POSIX_MAP_SFU20); -} - -static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e ) -{ - return nss_ad_generic_init(e, WB_POSIX_MAP_RFC2307); -} - - -/************************************************************************ - ***********************************************************************/ - -static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e, - const struct dom_sid *sid, - TALLOC_CTX *mem_ctx, - const char **homedir, - const char **shell, - const char **gecos, - gid_t *p_gid ) -{ - const char *attrs[] = {NULL, /* attr_homedir */ - NULL, /* attr_shell */ - NULL, /* attr_gecos */ - NULL, /* attr_gidnumber */ - NULL }; - char *filter = NULL; - LDAPMessage *msg_internal = NULL; - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - char *sidstr = NULL; - struct idmap_domain *dom; - struct idmap_ad_context *ctx; - - DEBUG(10, ("nss_ad_get_info called for sid [%s] in domain '%s'\n", - sid_string_dbg(sid), e->domain?e->domain:"NULL")); - - /* Only do query if we are online */ - if (idmap_is_offline()) { - return NT_STATUS_FILE_IS_OFFLINE; - } - - dom = talloc_get_type(e->state, struct idmap_domain); - ctx = talloc_get_type(dom->private_data, struct idmap_ad_context); - - ads_status = ad_idmap_cached_connection(dom); - if (!ADS_ERR_OK(ads_status)) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - if (!ctx->ad_schema) { - DEBUG(10, ("nss_ad_get_info: no ad_schema configured!\n")); - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - if (!sid || !homedir || !shell || !gecos) { - return NT_STATUS_INVALID_PARAMETER; - } - - /* Have to do our own query */ - - DEBUG(10, ("nss_ad_get_info: no ads connection given, doing our " - "own query\n")); - - attrs[0] = ctx->ad_schema->posix_homedir_attr; - attrs[1] = ctx->ad_schema->posix_shell_attr; - attrs[2] = ctx->ad_schema->posix_gecos_attr; - attrs[3] = ctx->ad_schema->posix_gidnumber_attr; - - sidstr = ldap_encode_ndr_dom_sid(mem_ctx, sid); - filter = talloc_asprintf(mem_ctx, "(objectSid=%s)", sidstr); - TALLOC_FREE(sidstr); - - if (!filter) { - nt_status = NT_STATUS_NO_MEMORY; - goto done; - } - - ads_status = ads_search_retry(ctx->ads, &msg_internal, filter, attrs); - if (!ADS_ERR_OK(ads_status)) { - nt_status = ads_ntstatus(ads_status); - goto done; - } - - *homedir = ads_pull_string(ctx->ads, mem_ctx, msg_internal, ctx->ad_schema->posix_homedir_attr); - *shell = ads_pull_string(ctx->ads, mem_ctx, msg_internal, ctx->ad_schema->posix_shell_attr); - *gecos = ads_pull_string(ctx->ads, mem_ctx, msg_internal, ctx->ad_schema->posix_gecos_attr); - - if (p_gid != NULL) { - uint32_t gid = UINT32_MAX; - bool ok; - - ok = ads_pull_uint32(ctx->ads, msg_internal, - ctx->ad_schema->posix_gidnumber_attr, - &gid); - if (ok) { - *p_gid = gid; - } else { - *p_gid = (gid_t)-1; - } - } - - nt_status = NT_STATUS_OK; - -done: - if (msg_internal) { - ads_msgfree(ctx->ads, msg_internal); - } - - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS nss_ad_map_to_alias(TALLOC_CTX *mem_ctx, - struct nss_domain_entry *e, - const char *name, - char **alias) -{ - const char *attrs[] = {NULL, /* attr_uid */ - NULL }; - char *filter = NULL; - LDAPMessage *msg = NULL; - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct idmap_domain *dom; - struct idmap_ad_context *ctx = NULL; - - /* Check incoming parameters */ - - if ( !e || !e->domain || !name || !*alias) { - nt_status = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - /* Only do query if we are online */ - - if (idmap_is_offline()) { - nt_status = NT_STATUS_FILE_IS_OFFLINE; - goto done; - } - - dom = talloc_get_type(e->state, struct idmap_domain); - ctx = talloc_get_type(dom->private_data, struct idmap_ad_context); - - ads_status = ad_idmap_cached_connection(dom); - if (!ADS_ERR_OK(ads_status)) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - if (!ctx->ad_schema) { - nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND; - goto done; - } - - attrs[0] = ctx->ad_schema->posix_uid_attr; - - filter = talloc_asprintf(mem_ctx, - "(sAMAccountName=%s)", - name); - if (!filter) { - nt_status = NT_STATUS_NO_MEMORY; - goto done; - } - - ads_status = ads_search_retry(ctx->ads, &msg, filter, attrs); - if (!ADS_ERR_OK(ads_status)) { - nt_status = ads_ntstatus(ads_status); - goto done; - } - - *alias = ads_pull_string(ctx->ads, mem_ctx, msg, ctx->ad_schema->posix_uid_attr); - - if (!*alias) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - nt_status = NT_STATUS_OK; - -done: - if (filter) { - talloc_destroy(filter); - } - if (msg) { - ads_msgfree(ctx->ads, msg); - } - - return nt_status; -} - -/********************************************************************** - *********************************************************************/ - -static NTSTATUS nss_ad_map_from_alias( TALLOC_CTX *mem_ctx, - struct nss_domain_entry *e, - const char *alias, - char **name ) -{ - const char *attrs[] = {"sAMAccountName", - NULL }; - char *filter = NULL; - LDAPMessage *msg = NULL; - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - char *username; - struct idmap_domain *dom; - struct idmap_ad_context *ctx = NULL; - - /* Check incoming parameters */ - - if ( !alias || !name) { - nt_status = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - /* Only do query if we are online */ - - if (idmap_is_offline()) { - nt_status = NT_STATUS_FILE_IS_OFFLINE; - goto done; - } - - dom = talloc_get_type(e->state, struct idmap_domain); - ctx = talloc_get_type(dom->private_data, struct idmap_ad_context); - - ads_status = ad_idmap_cached_connection(dom); - if (!ADS_ERR_OK(ads_status)) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - if (!ctx->ad_schema) { - nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND; - goto done; - } - - filter = talloc_asprintf(mem_ctx, - "(%s=%s)", - ctx->ad_schema->posix_uid_attr, - alias); - if (!filter) { - nt_status = NT_STATUS_NO_MEMORY; - goto done; - } - - ads_status = ads_search_retry(ctx->ads, &msg, filter, attrs); - if (!ADS_ERR_OK(ads_status)) { - nt_status = ads_ntstatus(ads_status); - goto done; - } - - username = ads_pull_string(ctx->ads, mem_ctx, msg, - "sAMAccountName"); - if (!username) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - *name = talloc_asprintf(mem_ctx, "%s\\%s", - lp_workgroup(), - username); - if (!*name) { - nt_status = NT_STATUS_NO_MEMORY; - goto done; - } - - nt_status = NT_STATUS_OK; - -done: - if (filter) { - talloc_destroy(filter); - } - if (msg) { - ads_msgfree(ctx->ads, msg); - } - - return nt_status; -} - /************************************************************************ Function dispatch tables for the idmap and nss plugins ***********************************************************************/ @@ -942,32 +571,6 @@ static struct idmap_methods ad_methods = { .sids_to_unixids = idmap_ad_sids_to_unixids, }; -/* The SFU and RFC2307 NSS plugins share everything but the init - function which sets the intended schema model to use */ - -static struct nss_info_methods nss_rfc2307_methods = { - .init = nss_rfc2307_init, - .get_nss_info = nss_ad_get_info, - .map_to_alias = nss_ad_map_to_alias, - .map_from_alias = nss_ad_map_from_alias, -}; - -static struct nss_info_methods nss_sfu_methods = { - .init = nss_sfu_init, - .get_nss_info = nss_ad_get_info, - .map_to_alias = nss_ad_map_to_alias, - .map_from_alias = nss_ad_map_from_alias, -}; - -static struct nss_info_methods nss_sfu20_methods = { - .init = nss_sfu20_init, - .get_nss_info = nss_ad_get_info, - .map_to_alias = nss_ad_map_to_alias, - .map_from_alias = nss_ad_map_from_alias, -}; - - - /************************************************************************ Initialize the plugins ***********************************************************************/ @@ -976,9 +579,7 @@ static_decl_idmap; NTSTATUS idmap_ad_init(void) { static NTSTATUS status_idmap_ad = NT_STATUS_UNSUCCESSFUL; - static NTSTATUS status_nss_rfc2307 = NT_STATUS_UNSUCCESSFUL; - static NTSTATUS status_nss_sfu = NT_STATUS_UNSUCCESSFUL; - static NTSTATUS status_nss_sfu20 = NT_STATUS_UNSUCCESSFUL; + static NTSTATUS status_ad_nss = NT_STATUS_UNSUCCESSFUL; /* Always register the AD method first in order to get the idmap_domain interface called */ @@ -990,27 +591,11 @@ NTSTATUS idmap_ad_init(void) return status_idmap_ad; } - if ( !NT_STATUS_IS_OK( status_nss_rfc2307 ) ) { - status_nss_rfc2307 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, - "rfc2307", &nss_rfc2307_methods ); - if ( !NT_STATUS_IS_OK(status_nss_rfc2307) ) - return status_nss_rfc2307; - } - - if ( !NT_STATUS_IS_OK( status_nss_sfu ) ) { - status_nss_sfu = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, - "sfu", &nss_sfu_methods ); - if ( !NT_STATUS_IS_OK(status_nss_sfu) ) - return status_nss_sfu; - } - - if ( !NT_STATUS_IS_OK( status_nss_sfu20 ) ) { - status_nss_sfu20 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, - "sfu20", &nss_sfu20_methods ); - if ( !NT_STATUS_IS_OK(status_nss_sfu20) ) - return status_nss_sfu20; + if ( !NT_STATUS_IS_OK( status_ad_nss ) ) { + status_ad_nss = idmap_ad_nss_init(); + if ( !NT_STATUS_IS_OK(status_ad_nss) ) + return status_ad_nss; } return NT_STATUS_OK; } - diff --git a/source3/winbindd/idmap_ad_nss.c b/source3/winbindd/idmap_ad_nss.c new file mode 100644 index 00000000000..8c5a13dceca --- /dev/null +++ b/source3/winbindd/idmap_ad_nss.c @@ -0,0 +1,531 @@ +/* + * idmap_ad: map between Active Directory and RFC 2307 or "Services for Unix" (SFU) Accounts + * + * Unix SMB/CIFS implementation. + * + * Winbind ADS backend functions + * + * Copyright (C) Andrew Tridgell 2001 + * Copyright (C) Andrew Bartlett 2003 + * Copyright (C) Gerald (Jerry) Carter 2004-2007 + * Copyright (C) Luke Howard 2001-2004 + * Copyright (C) Michael Adam 2008,2010 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "includes.h" +#include "winbindd.h" +#include "../libds/common/flags.h" +#include "ads.h" +#include "libads/ldap_schema.h" +#include "nss_info.h" +#include "idmap.h" +#include "../libcli/ldap/ldap_ndr.h" +#include "../libcli/security/security.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +#define CHECK_ALLOC_DONE(mem) do { \ + if (!mem) { \ + DEBUG(0, ("Out of memory!\n")); \ + ret = NT_STATUS_NO_MEMORY; \ + goto done; \ + } \ +} while (0) + +struct idmap_ad_context { + ADS_STRUCT *ads; + struct posix_schema *ad_schema; + enum wb_posix_mapping ad_map_type; /* WB_POSIX_MAP_UNKNOWN */ +}; + +/************************************************************************ + ***********************************************************************/ + +static ADS_STATUS ad_idmap_cached_connection(struct idmap_domain *dom) +{ + ADS_STATUS status; + struct idmap_ad_context * ctx; + + DEBUG(10, ("ad_idmap_cached_connection: called for domain '%s'\n", + dom->name)); + + ctx = talloc_get_type(dom->private_data, struct idmap_ad_context); + + status = ads_idmap_cached_connection(&ctx->ads, dom->name); + if (!ADS_ERR_OK(status)) { + return status; + } + + ctx = talloc_get_type(dom->private_data, struct idmap_ad_context); + + /* if we have a valid ADS_STRUCT and the schema model is + defined, then we can return here. */ + + if ( ctx->ad_schema ) { + return ADS_SUCCESS; + } + + /* Otherwise, set the schema model */ + + if ( (ctx->ad_map_type == WB_POSIX_MAP_SFU) || + (ctx->ad_map_type == WB_POSIX_MAP_SFU20) || + (ctx->ad_map_type == WB_POSIX_MAP_RFC2307) ) + { + status = ads_check_posix_schema_mapping( + ctx, ctx->ads, ctx->ad_map_type, &ctx->ad_schema); + if ( !ADS_ERR_OK(status) ) { + DEBUG(2,("ad_idmap_cached_connection: Failed to obtain schema details!\n")); + } + } + + return status; +} + +/* + * nss_info_{sfu,sfu20,rfc2307} + */ + +/************************************************************************ + Initialize the {sfu,sfu20,rfc2307} state + ***********************************************************************/ + +static const char *wb_posix_map_unknown_string = "WB_POSIX_MAP_UNKNOWN"; +static const char *wb_posix_map_template_string = "WB_POSIX_MAP_TEMPLATE"; +static const char *wb_posix_map_sfu_string = "WB_POSIX_MAP_SFU"; +static const char *wb_posix_map_sfu20_string = "WB_POSIX_MAP_SFU20"; +static const char *wb_posix_map_rfc2307_string = "WB_POSIX_MAP_RFC2307"; +static const char *wb_posix_map_unixinfo_string = "WB_POSIX_MAP_UNIXINFO"; + +static const char *ad_map_type_string(enum wb_posix_mapping map_type) +{ + switch (map_type) { + case WB_POSIX_MAP_TEMPLATE: + return wb_posix_map_template_string; + case WB_POSIX_MAP_SFU: + return wb_posix_map_sfu_string; + case WB_POSIX_MAP_SFU20: + return wb_posix_map_sfu20_string; + case WB_POSIX_MAP_RFC2307: + return wb_posix_map_rfc2307_string; + case WB_POSIX_MAP_UNIXINFO: + return wb_posix_map_unixinfo_string; + default: + return wb_posix_map_unknown_string; + } +} + +static NTSTATUS nss_ad_generic_init(struct nss_domain_entry *e, + enum wb_posix_mapping new_ad_map_type) +{ + struct idmap_domain *dom; + struct idmap_ad_context *ctx; + + if (e->state != NULL) { + dom = talloc_get_type(e->state, struct idmap_domain); + } else { + dom = talloc_zero(e, struct idmap_domain); + if (dom == NULL) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + e->state = dom; + } + + if (e->domain != NULL) { + dom->name = talloc_strdup(dom, e->domain); + if (dom->name == NULL) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + } + + if (dom->private_data != NULL) { + ctx = talloc_get_type(dom->private_data, + struct idmap_ad_context); + } else { + ctx = talloc_zero(dom, struct idmap_ad_context); + if (ctx == NULL) { + DEBUG(0, ("Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + ctx->ad_map_type = WB_POSIX_MAP_RFC2307; + dom->private_data = ctx; + } + + if ((ctx->ad_map_type != WB_POSIX_MAP_UNKNOWN) && + (ctx->ad_map_type != new_ad_map_type)) + { + DEBUG(2, ("nss_ad_generic_init: " + "Warning: overriding previously set posix map type " + "%s for domain %s with map type %s.\n", + ad_map_type_string(ctx->ad_map_type), + dom->name, + ad_map_type_string(new_ad_map_type))); + } + + ctx->ad_map_type = new_ad_map_type; + + return NT_STATUS_OK; +} + +static NTSTATUS nss_sfu_init( struct nss_domain_entry *e ) +{ + return nss_ad_generic_init(e, WB_POSIX_MAP_SFU); +} + +static NTSTATUS nss_sfu20_init( struct nss_domain_entry *e ) +{ + return nss_ad_generic_init(e, WB_POSIX_MAP_SFU20); +} + +static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e ) +{ + return nss_ad_generic_init(e, WB_POSIX_MAP_RFC2307); +} + + +/************************************************************************ + ***********************************************************************/ + +static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e, + const struct dom_sid *sid, + TALLOC_CTX *mem_ctx, + const char **homedir, + const char **shell, + const char **gecos, + gid_t *p_gid ) +{ + const char *attrs[] = {NULL, /* attr_homedir */ + NULL, /* attr_shell */ + NULL, /* attr_gecos */ + NULL, /* attr_gidnumber */ + NULL }; + char *filter = NULL; + LDAPMessage *msg_internal = NULL; + ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + char *sidstr = NULL; + struct idmap_domain *dom; + struct idmap_ad_context *ctx; + + DEBUG(10, ("nss_ad_get_info called for sid [%s] in domain '%s'\n", + sid_string_dbg(sid), e->domain?e->domain:"NULL")); + + /* Only do query if we are online */ + if (idmap_is_offline()) { + return NT_STATUS_FILE_IS_OFFLINE; + } + + dom = talloc_get_type(e->state, struct idmap_domain); + ctx = talloc_get_type(dom->private_data, struct idmap_ad_context); + + ads_status = ad_idmap_cached_connection(dom); + if (!ADS_ERR_OK(ads_status)) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (!ctx->ad_schema) { + DEBUG(10, ("nss_ad_get_info: no ad_schema configured!\n")); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (!sid || !homedir || !shell || !gecos) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* Have to do our own query */ + + DEBUG(10, ("nss_ad_get_info: no ads connection given, doing our " + "own query\n")); + + attrs[0] = ctx->ad_schema->posix_homedir_attr; + attrs[1] = ctx->ad_schema->posix_shell_attr; + attrs[2] = ctx->ad_schema->posix_gecos_attr; + attrs[3] = ctx->ad_schema->posix_gidnumber_attr; + + sidstr = ldap_encode_ndr_dom_sid(mem_ctx, sid); + filter = talloc_asprintf(mem_ctx, "(objectSid=%s)", sidstr); + TALLOC_FREE(sidstr); + + if (!filter) { + nt_status = NT_STATUS_NO_MEMORY; + goto done; + } + + ads_status = ads_search_retry(ctx->ads, &msg_internal, filter, attrs); + if (!ADS_ERR_OK(ads_status)) { + nt_status = ads_ntstatus(ads_status); + goto done; + } + + *homedir = ads_pull_string(ctx->ads, mem_ctx, msg_internal, ctx->ad_schema->posix_homedir_attr); + *shell = ads_pull_string(ctx->ads, mem_ctx, msg_internal, ctx->ad_schema->posix_shell_attr); + *gecos = ads_pull_string(ctx->ads, mem_ctx, msg_internal, ctx->ad_schema->posix_gecos_attr); + + if (p_gid != NULL) { + uint32_t gid = UINT32_MAX; + bool ok; + + ok = ads_pull_uint32(ctx->ads, msg_internal, + ctx->ad_schema->posix_gidnumber_attr, + &gid); + if (ok) { + *p_gid = gid; + } else { + *p_gid = (gid_t)-1; + } + } + + nt_status = NT_STATUS_OK; + +done: + if (msg_internal) { + ads_msgfree(ctx->ads, msg_internal); + } + + return nt_status; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS nss_ad_map_to_alias(TALLOC_CTX *mem_ctx, + struct nss_domain_entry *e, + const char *name, + char **alias) +{ + const char *attrs[] = {NULL, /* attr_uid */ + NULL }; + char *filter = NULL; + LDAPMessage *msg = NULL; + ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct idmap_domain *dom; + struct idmap_ad_context *ctx = NULL; + + /* Check incoming parameters */ + + if ( !e || !e->domain || !name || !*alias) { + nt_status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + /* Only do query if we are online */ + + if (idmap_is_offline()) { + nt_status = NT_STATUS_FILE_IS_OFFLINE; + goto done; + } + + dom = talloc_get_type(e->state, struct idmap_domain); + ctx = talloc_get_type(dom->private_data, struct idmap_ad_context); + + ads_status = ad_idmap_cached_connection(dom); + if (!ADS_ERR_OK(ads_status)) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (!ctx->ad_schema) { + nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + goto done; + } + + attrs[0] = ctx->ad_schema->posix_uid_attr; + + filter = talloc_asprintf(mem_ctx, + "(sAMAccountName=%s)", + name); + if (!filter) { + nt_status = NT_STATUS_NO_MEMORY; + goto done; + } + + ads_status = ads_search_retry(ctx->ads, &msg, filter, attrs); + if (!ADS_ERR_OK(ads_status)) { + nt_status = ads_ntstatus(ads_status); + goto done; + } + + *alias = ads_pull_string(ctx->ads, mem_ctx, msg, ctx->ad_schema->posix_uid_attr); + + if (!*alias) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + nt_status = NT_STATUS_OK; + +done: + if (filter) { + talloc_destroy(filter); + } + if (msg) { + ads_msgfree(ctx->ads, msg); + } + + return nt_status; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS nss_ad_map_from_alias( TALLOC_CTX *mem_ctx, + struct nss_domain_entry *e, + const char *alias, + char **name ) +{ + const char *attrs[] = {"sAMAccountName", + NULL }; + char *filter = NULL; + LDAPMessage *msg = NULL; + ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + char *username; + struct idmap_domain *dom; + struct idmap_ad_context *ctx = NULL; + + /* Check incoming parameters */ + + if ( !alias || !name) { + nt_status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + /* Only do query if we are online */ + + if (idmap_is_offline()) { + nt_status = NT_STATUS_FILE_IS_OFFLINE; + goto done; + } + + dom = talloc_get_type(e->state, struct idmap_domain); + ctx = talloc_get_type(dom->private_data, struct idmap_ad_context); + + ads_status = ad_idmap_cached_connection(dom); + if (!ADS_ERR_OK(ads_status)) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (!ctx->ad_schema) { + nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + goto done; + } + + filter = talloc_asprintf(mem_ctx, + "(%s=%s)", + ctx->ad_schema->posix_uid_attr, + alias); + if (!filter) { + nt_status = NT_STATUS_NO_MEMORY; + goto done; + } + + ads_status = ads_search_retry(ctx->ads, &msg, filter, attrs); + if (!ADS_ERR_OK(ads_status)) { + nt_status = ads_ntstatus(ads_status); + goto done; + } + + username = ads_pull_string(ctx->ads, mem_ctx, msg, + "sAMAccountName"); + if (!username) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + *name = talloc_asprintf(mem_ctx, "%s\\%s", + lp_workgroup(), + username); + if (!*name) { + nt_status = NT_STATUS_NO_MEMORY; + goto done; + } + + nt_status = NT_STATUS_OK; + +done: + if (filter) { + talloc_destroy(filter); + } + if (msg) { + ads_msgfree(ctx->ads, msg); + } + + return nt_status; +} + +/************************************************************************ + Function dispatch tables for the idmap and nss plugins + ***********************************************************************/ + +/* The SFU and RFC2307 NSS plugins share everything but the init + function which sets the intended schema model to use */ + +static struct nss_info_methods nss_rfc2307_methods = { + .init = nss_rfc2307_init, + .get_nss_info = nss_ad_get_info, + .map_to_alias = nss_ad_map_to_alias, + .map_from_alias = nss_ad_map_from_alias, +}; + +static struct nss_info_methods nss_sfu_methods = { + .init = nss_sfu_init, + .get_nss_info = nss_ad_get_info, + .map_to_alias = nss_ad_map_to_alias, + .map_from_alias = nss_ad_map_from_alias, +}; + +static struct nss_info_methods nss_sfu20_methods = { + .init = nss_sfu20_init, + .get_nss_info = nss_ad_get_info, + .map_to_alias = nss_ad_map_to_alias, + .map_from_alias = nss_ad_map_from_alias, +}; + + + +/************************************************************************ + Initialize the plugins + ***********************************************************************/ + +NTSTATUS idmap_ad_nss_init(void) +{ + static NTSTATUS status_nss_rfc2307 = NT_STATUS_UNSUCCESSFUL; + static NTSTATUS status_nss_sfu = NT_STATUS_UNSUCCESSFUL; + static NTSTATUS status_nss_sfu20 = NT_STATUS_UNSUCCESSFUL; + + if ( !NT_STATUS_IS_OK( status_nss_rfc2307 ) ) { + status_nss_rfc2307 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, + "rfc2307", &nss_rfc2307_methods ); + if ( !NT_STATUS_IS_OK(status_nss_rfc2307) ) + return status_nss_rfc2307; + } + + if ( !NT_STATUS_IS_OK( status_nss_sfu ) ) { + status_nss_sfu = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, + "sfu", &nss_sfu_methods ); + if ( !NT_STATUS_IS_OK(status_nss_sfu) ) + return status_nss_sfu; + } + + if ( !NT_STATUS_IS_OK( status_nss_sfu20 ) ) { + status_nss_sfu20 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, + "sfu20", &nss_sfu20_methods ); + if ( !NT_STATUS_IS_OK(status_nss_sfu20) ) + return status_nss_sfu20; + } + + return NT_STATUS_OK; +} diff --git a/source3/winbindd/idmap_proto.h b/source3/winbindd/idmap_proto.h index ea96d728713..84cc2f01cab 100644 --- a/source3/winbindd/idmap_proto.h +++ b/source3/winbindd/idmap_proto.h @@ -63,4 +63,6 @@ struct id_map **id_map_ptrs_init(TALLOC_CTX *mem_ctx, size_t num_ids); /* max number of ids requested per LDAP batch query */ #define IDMAP_LDAP_MAX_IDS 30 +NTSTATUS idmap_ad_nss_init(void); + #endif /* _WINBINDD_IDMAP_PROTO_H_ */ diff --git a/source3/winbindd/wscript_build b/source3/winbindd/wscript_build index 3ee280c9412..eab788f1837 100644 --- a/source3/winbindd/wscript_build +++ b/source3/winbindd/wscript_build @@ -20,7 +20,7 @@ bld.SAMBA3_SUBSYSTEM('IDMAP_HASH', enabled=bld.SAMBA3_IS_ENABLED_MODULE('idmap_hash')) bld.SAMBA3_SUBSYSTEM('IDMAP_AD', - source='idmap_ad.c', + source='idmap_ad.c idmap_ad_nss.c', deps='ads nss_info', enabled=bld.SAMBA3_IS_ENABLED_MODULE('idmap_ad'))