]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
idmap_ad: Separate out the nss functions
authorVolker Lendecke <vl@samba.org>
Tue, 29 Mar 2016 14:03:04 +0000 (16:03 +0200)
committerVolker Lendecke <vl@samba.org>
Fri, 15 Apr 2016 13:32:11 +0000 (15:32 +0200)
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 <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/winbindd/idmap_ad.c
source3/winbindd/idmap_ad_nss.c [new file with mode: 0644]
source3/winbindd/idmap_proto.h
source3/winbindd/wscript_build

index e5dea208436b718555873f58fd56818d45e6903a..8f15ecb54339d17dc5aabdfc9b12aca7aad34f36 100644 (file)
@@ -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 (file)
index 0000000..8c5a13d
--- /dev/null
@@ -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 <abartlet@samba.org> 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 <http://www.gnu.org/licenses/>.
+ */
+
+#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;
+}
index ea96d728713875758575b1723d4c788a263ff154..84cc2f01cabb34b7c81665586ad9f08b05a71f75 100644 (file)
@@ -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_ */
index 3ee280c9412db56b3c62f1a5f11ae54e100cbfd0..eab788f18371a5a1d6d622cd4aa26c95a3670335 100644 (file)
@@ -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'))