idmap_ad: Restore querying SFU nss info
authorVolker Lendecke <vl@samba.org>
Thu, 29 Dec 2016 10:27:58 +0000 (10:27 +0000)
committerVolker Lendecke <vl@samba.org>
Mon, 2 Jan 2017 17:04:14 +0000 (18:04 +0100)
With the last commit the getpwsid call did not look at the winbind
nss info parameter anymore. This restores it for the idmap ad backend
with slightly different semantics and configuration: We now have the
unix_primary_group and unix_nss_info domain-specific parameters for
idmap config. This enables overriding the Windows primary group with
the unix one.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Uri Simchoni <uri@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
docs-xml/manpages/idmap_ad.8.xml
source3/winbindd/idmap_ad.c

index 5876c4686686d51769fc74c61bf8de8d5a9dc74e..58e7f52431899e69fd23c810ec4f7186c81c0636 100644 (file)
                        via the "primaryGroupID" LDAP attribute.
                </para></listitem>
                </varlistentry>
+               <varlistentry>
+               <term>unix_primary_group = yes/no</term>
+               <listitem><para>
+                 Defines whether to retrieve the user's primary group
+                 from the SFU attributes.
+               </para></listitem>
+               </varlistentry>
+               <varlistentry>
+               <term>unix_nss_info = yes/no</term>
+               <listitem><para>
+                 Defines whether to retrieve the login shell and
+                 home directory from the SFU attributes.
+               </para></listitem>
+               </varlistentry>
        </variablelist>
 </refsect1>
 
index c385cf0e5e7b13100e82977ca9b9ca64cc9a5a82..f406392184a0bde937d14d81d23a5295b133ab77 100644 (file)
@@ -39,8 +39,14 @@ struct idmap_ad_context {
        struct tldap_context *ld;
        struct idmap_ad_schema_names *schema;
        const char *default_nc;
+
+       bool unix_primary_group;
+       bool unix_nss_info;
 };
 
+static NTSTATUS idmap_ad_get_context(struct idmap_domain *dom,
+                                    struct idmap_ad_context **pctx);
+
 static char *get_schema_path(TALLOC_CTX *mem_ctx, struct tldap_context *ld)
 {
        struct tldap_message *rootdse;
@@ -396,6 +402,11 @@ static NTSTATUS idmap_ad_context_create(TALLOC_CTX *mem_ctx,
                return NT_STATUS_NO_MEMORY;
        }
 
+       ctx->unix_primary_group = lp_parm_bool(
+               -1, schema_config_option, "unix_primary_group", false);
+       ctx->unix_nss_info = lp_parm_bool(
+               -1, schema_config_option, "unix_nss_info", false);
+
        schema_mode = lp_parm_const_string(
                -1, schema_config_option, "schema_mode", "rfc2307");
        TALLOC_FREE(schema_config_option);
@@ -412,8 +423,107 @@ static NTSTATUS idmap_ad_context_create(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
+static NTSTATUS idmap_ad_query_user(struct idmap_domain *domain,
+                                   struct wbint_userinfo *info)
+{
+       struct idmap_ad_context *ctx;
+       TLDAPRC rc;
+       NTSTATUS status;
+       char *sidstr, *filter;
+       const char *attrs[4];
+       size_t i, num_msgs;
+       struct tldap_message **msgs;
+
+       status = idmap_ad_get_context(domain, &ctx);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (!(ctx->unix_primary_group || ctx->unix_nss_info)) {
+               return NT_STATUS_OK;
+       }
+
+       attrs[0] = ctx->schema->gid;
+       attrs[1] = ctx->schema->gecos;
+       attrs[2] = ctx->schema->dir;
+       attrs[3] = ctx->schema->shell;
+
+       sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), &info->user_sid);
+       if (sidstr == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       filter = talloc_asprintf(talloc_tos(), "(objectsid=%s)", sidstr);
+       TALLOC_FREE(sidstr);
+       if (filter == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       DBG_DEBUG("Filter: [%s]\n", filter);
+
+       rc = tldap_search(ctx->ld, ctx->default_nc, TLDAP_SCOPE_SUB, filter,
+                         attrs, ARRAY_SIZE(attrs), 0, NULL, 0, NULL, 0,
+                         0, 0, 0, talloc_tos(), &msgs);
+       if (!TLDAP_RC_IS_SUCCESS(rc)) {
+               return NT_STATUS_LDAP(TLDAP_RC_V(rc));
+       }
+
+       TALLOC_FREE(filter);
+
+       num_msgs = talloc_array_length(msgs);
+
+       for (i=0; i<num_msgs; i++) {
+               struct tldap_message *msg = msgs[i];
+
+               if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
+                       continue;
+               }
+
+               if (ctx->unix_primary_group) {
+                       bool ok;
+                       uint32_t gid;
+
+                       ok = tldap_pull_uint32(msg, ctx->schema->gid, &gid);
+                       if (ok) {
+                               DBG_DEBUG("Setting primary group "
+                                         "to %"PRIu32" from attr %s\n",
+                                         gid, ctx->schema->gid);
+                               info->primary_gid = gid;
+                       }
+               }
+
+               if (ctx->unix_nss_info) {
+                       char *attr;
+
+                       attr = tldap_talloc_single_attribute(
+                               msg, ctx->schema->dir, talloc_tos());
+                       if (attr != NULL) {
+                               info->homedir = talloc_move(info, &attr);
+                       }
+                       TALLOC_FREE(attr);
+
+                       attr = tldap_talloc_single_attribute(
+                               msg, ctx->schema->shell, talloc_tos());
+                       if (attr != NULL) {
+                               info->shell = talloc_move(info, &attr);
+                       }
+                       TALLOC_FREE(attr);
+
+                       attr = tldap_talloc_single_attribute(
+                               msg, ctx->schema->gecos, talloc_tos());
+                       if (attr != NULL) {
+                               info->full_name = talloc_move(info, &attr);
+                       }
+                       TALLOC_FREE(attr);
+               }
+       }
+
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom)
 {
+       dom->query_user = idmap_ad_query_user;
        dom->private_data = NULL;
        return NT_STATUS_OK;
 }