r15697: I take no comments as no objections :)
authorGünther Deschner <gd@samba.org>
Thu, 18 May 2006 16:08:28 +0000 (16:08 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:17:08 +0000 (11:17 -0500)
Expand the "winbind nss info" to also take "rfc2307" to support the
plain posix attributes LDAP schema from win2k3-r2.

This work is based on patches from Howard Wilkinson and Bob Gautier
(and closes bug #3345).

Guenther
(This used to be commit 52423e01dc209ba5abde808a446287714ed11567)

source3/Makefile.in
source3/include/ads.h
source3/libads/ads_struct.c
source3/libads/ldap.c
source3/libads/ldap_schema.c [new file with mode: 0644]
source3/nsswitch/winbindd_ads.c
source3/nsswitch/winbindd_user.c
source3/sam/idmap_ad.c
source3/sam/idmap_util.c
source3/sam/nss_info.c [new file with mode: 0644]

index 9ff74f60b81c4440988c154266376cf6c89e5e47..25927be3efd00406b690fc4e959e6bb833ab3cd2 100644 (file)
@@ -243,7 +243,8 @@ LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
              libads/disp_sec.o libads/ads_utils.o libads/ldap_utils.o \
             libads/authdata.o libads/cldap.o
 
-LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o
+LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o \
+                   libads/ldap_schema.o sam/nss_info.o
 
 SECRETS_OBJ = passdb/secrets.o passdb/machine_sid.o 
 
index 48b9bbffa02d44f41d23ab46c6c9ba6ec0c3be98..e93d36a5cab92053f9588b80363e4e71f0ffcef2 100644 (file)
@@ -4,6 +4,13 @@
   basically this is a wrapper around ldap
 */
 
+enum wb_posix_mapping {
+       WB_POSIX_MAP_TEMPLATE   = 0, 
+       WB_POSIX_MAP_SFU        = 1, 
+       WB_POSIX_MAP_RFC2307    = 2,
+       WB_POSIX_MAP_UNIXINFO   = 3
+};
+
 typedef struct {
        void *ld; /* the active ldap structure */
        struct in_addr ldap_ip; /* the ip of the active connection, if any */
@@ -42,11 +49,12 @@ typedef struct {
 
        /* info derived from the servers schema */
        struct {
-               char *sfu_homedir_attr;
-               char *sfu_shell_attr;
-               char *sfu_uidnumber_attr;
-               char *sfu_gidnumber_attr;
-               char *sfu_gecos_attr;
+               enum wb_posix_mapping map_type;
+               char *posix_homedir_attr;
+               char *posix_shell_attr;
+               char *posix_uidnumber_attr;
+               char *posix_gidnumber_attr;
+               char *posix_gecos_attr;
        } schema;
 
 } ADS_STRUCT;
@@ -83,6 +91,13 @@ typedef void **ADS_MODLIST;
 #define ADS_ERR_OK(status) ((status.error_type == ENUM_ADS_ERROR_NT) ? NT_STATUS_IS_OK(status.err.nt_status):(status.err.rc == 0))
 #define ADS_SUCCESS ADS_ERROR(0)
 
+#define ADS_ERROR_HAVE_NO_MEMORY(x) do { \
+        if (!(x)) {\
+                return ADS_ERROR(LDAP_NO_MEMORY);\
+        }\
+} while (0)
+
+
 /* time between reconnect attempts */
 #define ADS_RECONNECT_TIME 5
 
@@ -100,6 +115,13 @@ typedef void **ADS_MODLIST;
 #define ADS_ATTR_SFU_SHELL_OID                 "1.2.840.113556.1.6.18.1.312"
 #define ADS_ATTR_SFU_GECOS_OID                 "1.2.840.113556.1.6.18.1.337"
 
+/* ldap attribute oids (RFC2307) */
+#define ADS_ATTR_RFC2307_UIDNUMBER_OID "1.3.6.1.1.1.1.0"
+#define ADS_ATTR_RFC2307_GIDNUMBER_OID "1.3.6.1.1.1.1.1"
+#define ADS_ATTR_RFC2307_HOMEDIR_OID   "1.3.6.1.1.1.1.3"
+#define ADS_ATTR_RFC2307_SHELL_OID     "1.3.6.1.1.1.1.4"
+#define ADS_ATTR_RFC2307_GECOS_OID     "1.3.6.1.1.1.1.2"
+
 /* ldap bitwise searches */
 #define ADS_LDAP_MATCHING_RULE_BIT_AND "1.2.840.113556.1.4.803"
 #define ADS_LDAP_MATCHING_RULE_BIT_OR  "1.2.840.113556.1.4.804"
index 48533c7ffb22d5a3f9e8346f6f3528944523f7ce..e546f2ae8ab3e31361e30669615679e7a4d38ff5 100644 (file)
@@ -135,11 +135,11 @@ void ads_destroy(ADS_STRUCT **ads)
                SAFE_FREE((*ads)->config.bind_path);
                SAFE_FREE((*ads)->config.ldap_server_name);
                
-               SAFE_FREE((*ads)->schema.sfu_uidnumber_attr);
-               SAFE_FREE((*ads)->schema.sfu_gidnumber_attr);
-               SAFE_FREE((*ads)->schema.sfu_shell_attr);
-               SAFE_FREE((*ads)->schema.sfu_homedir_attr);
-               SAFE_FREE((*ads)->schema.sfu_gecos_attr);
+               SAFE_FREE((*ads)->schema.posix_uidnumber_attr);
+               SAFE_FREE((*ads)->schema.posix_gidnumber_attr);
+               SAFE_FREE((*ads)->schema.posix_shell_attr);
+               SAFE_FREE((*ads)->schema.posix_homedir_attr);
+               SAFE_FREE((*ads)->schema.posix_gecos_attr);
                
                ZERO_STRUCTP(*ads);
 
index b208e58504c2cc231720d3aa004a636699a322a0..4a14527a22ba682eeecd9e3c0f63ec37d2b2966b 100644 (file)
@@ -2322,49 +2322,6 @@ static time_t ads_parse_time(const char *str)
        return timegm(&tm);
 }
 
-
-const char *ads_get_attrname_by_oid(ADS_STRUCT *ads, const char *schema_path, TALLOC_CTX *mem_ctx, const char * OID)
-{
-       ADS_STATUS rc;
-       int count = 0;
-       void *res = NULL;
-       char *expr = NULL;
-       const char *attrs[] = { "lDAPDisplayName", NULL };
-       char *result;
-
-       if (ads == NULL || mem_ctx == NULL || OID == NULL) {
-               goto failed;
-       }
-
-       expr = talloc_asprintf(mem_ctx, "(attributeId=%s)", OID);
-       if (expr == NULL) {
-               goto failed;
-       }
-
-       rc = ads_do_search_retry(ads, schema_path, LDAP_SCOPE_SUBTREE, 
-               expr, attrs, &res);
-       if (!ADS_ERR_OK(rc)) {
-               goto failed;
-       }
-
-       count = ads_count_replies(ads, res);
-       if (count == 0 || !res) {
-               goto failed;
-       }
-
-       result = ads_pull_string(ads, mem_ctx, res, "lDAPDisplayName");
-       ads_msgfree(ads, res);
-
-       return result;
-       
-failed:
-       DEBUG(0,("ads_get_attrname_by_oid: failed to retrieve name for oid: %s\n", 
-               OID));
-       
-       ads_msgfree(ads, res);
-       return NULL;
-}
-
 /**
  * Find the servers name and realm - this can be done before authentication 
  *  The ldapServiceName field on w2k  looks like this:
@@ -2436,113 +2393,6 @@ done:
        return status;
 }
 
-/*********************************************************************
-*********************************************************************/
-
-static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **schema_path)
-{
-       ADS_STATUS status;
-       void *res;
-       const char *schema;
-       const char *attrs[] = { "schemaNamingContext", NULL };
-
-       status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
-       if (!ADS_ERR_OK(status)) {
-               return status;
-       }
-
-       if ( (schema = ads_pull_string(ads, mem_ctx, res, "schemaNamingContext")) == NULL ) {
-               return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
-       }
-
-       if ( (*schema_path = talloc_strdup(mem_ctx, schema)) == NULL ) {
-               return ADS_ERROR(LDAP_NO_MEMORY);
-       }
-
-       ads_msgfree(ads, res);
-
-       return status;
-}
-
-/**
- * Check for "Services for Unix"-Schema and load some attributes into the ADS_STRUCT
- * @param ads connection to ads server
- * @return BOOL status of search (False if one or more attributes couldn't be
- * found in Active Directory)
- **/ 
-BOOL ads_check_sfu_mapping(ADS_STRUCT *ads) 
-{ 
-       BOOL ret = False; 
-       TALLOC_CTX *ctx = NULL; 
-       const char *gidnumber, *uidnumber, *homedir, *shell, *gecos;
-       char *schema_path = NULL;
-       ADS_STRUCT *ads_s = ads;
-       ADS_STATUS status;
-
-       if ( (ctx = talloc_init("ads_check_sfu_mapping")) == NULL ) {
-               goto done;
-       }
-
-       /* establish a new ldap tcp session if necessary */
-
-       if ( !ads->ld ) {
-               if ( (ads_s = ads_init( ads->server.realm, ads->server.workgroup, 
-                       ads->server.ldap_server )) == NULL )
-               {
-                       goto done;
-               }
-
-               ads_s->auth.flags = ADS_AUTH_ANON_BIND;
-               status = ads_connect( ads_s );
-               if ( !ADS_ERR_OK(status))
-                       goto done;
-       }
-
-       status = ads_schema_path( ads, ctx, &schema_path );
-       if ( !ADS_ERR_OK(status) ) {
-               DEBUG(3,("ads_check_sfu_mapping: Unable to retrieve schema DN!\n"));
-               goto done;
-       }
-
-       gidnumber = ads_get_attrname_by_oid(ads_s, schema_path, ctx, ADS_ATTR_SFU_GIDNUMBER_OID);
-       if (gidnumber == NULL)
-               goto done;
-       ads->schema.sfu_gidnumber_attr = SMB_STRDUP(gidnumber);
-
-       uidnumber = ads_get_attrname_by_oid(ads_s, schema_path, ctx, ADS_ATTR_SFU_UIDNUMBER_OID);
-       if (uidnumber == NULL)
-               goto done;
-       ads->schema.sfu_uidnumber_attr = SMB_STRDUP(uidnumber);
-
-       homedir = ads_get_attrname_by_oid(ads_s, schema_path, ctx, ADS_ATTR_SFU_HOMEDIR_OID);
-       if (homedir == NULL)
-               goto done;
-       ads->schema.sfu_homedir_attr = SMB_STRDUP(homedir);
-       
-       shell = ads_get_attrname_by_oid(ads_s, schema_path, ctx, ADS_ATTR_SFU_SHELL_OID);
-       if (shell == NULL)
-               goto done;
-       ads->schema.sfu_shell_attr = SMB_STRDUP(shell);
-
-       gecos = ads_get_attrname_by_oid(ads_s, schema_path, ctx, ADS_ATTR_SFU_GECOS_OID);
-       if (gecos == NULL)
-               goto done;
-       ads->schema.sfu_gecos_attr = SMB_STRDUP(gecos);
-
-       ret = True;
-done:
-       /* free any temporary ads connections */
-       if ( ads_s != ads ) {
-               ads_destroy( &ads_s );
-       }
-
-       if (ctx) {
-               talloc_destroy(ctx);
-       }
-
-       return ret;
-}
-
 /**
  * find the domain sid for our domain
  * @param ads connection to ads server
diff --git a/source3/libads/ldap_schema.c b/source3/libads/ldap_schema.c
new file mode 100644 (file)
index 0000000..a0c7352
--- /dev/null
@@ -0,0 +1,329 @@
+/* 
+   Unix SMB/CIFS implementation.
+   ads (active directory) utility library
+   Copyright (C) Guenther Deschner 2005-2006
+   Copyright (C) Gerald (Jerry) Carter 2006
+   
+   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 2 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, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#ifdef HAVE_LDAP
+
+ADS_STATUS ads_get_attrnames_by_oids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+                                    const char *schema_path,
+                                    const char **OIDs, size_t num_OIDs, 
+                                    char ***OIDs_out, char ***names, size_t *count)
+{
+       ADS_STATUS status;
+       void *res = NULL;
+       LDAPMessage *msg;
+       char *expr = NULL;
+       const char *attrs[] = { "lDAPDisplayName", "attributeId", NULL };
+       int i = 0, p = 0;
+       
+       if (!ads || !mem_ctx || !names || !count || !OIDs || !OIDs_out) {
+               return ADS_ERROR(LDAP_PARAM_ERROR);
+       }
+
+       if (num_OIDs == 0 || OIDs[0] == NULL) {
+               return ADS_ERROR_NT(NT_STATUS_NONE_MAPPED);
+       }
+
+       if ((expr = talloc_asprintf(mem_ctx, "(|")) == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       for (i=0; i<num_OIDs; i++) {
+
+               if ((expr = talloc_asprintf_append(expr, "(attributeId=%s)", 
+                                                  OIDs[i])) == NULL) {
+                       return ADS_ERROR(LDAP_NO_MEMORY);
+               }
+       }
+
+       if ((expr = talloc_asprintf_append(expr, ")")) == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       status = ads_do_search_retry(ads, schema_path, 
+                                    LDAP_SCOPE_SUBTREE, expr, attrs, &res);
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
+       *count = ads_count_replies(ads, res);
+       if (*count == 0 || !res) {
+               status = ADS_ERROR_NT(NT_STATUS_NONE_MAPPED);
+               goto out;
+       }
+
+       if (((*names) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) {
+               status = ADS_ERROR(LDAP_NO_MEMORY);
+               goto out;
+       }
+       if (((*OIDs_out) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) {
+               status = ADS_ERROR(LDAP_NO_MEMORY);
+               goto out;
+       }
+
+       for (msg = ads_first_entry(ads, res); msg != NULL; 
+            msg = ads_next_entry(ads, msg)) {
+
+               (*names)[p]     = ads_pull_string(ads, mem_ctx, msg, 
+                                                 "lDAPDisplayName");
+               (*OIDs_out)[p]  = ads_pull_string(ads, mem_ctx, msg, 
+                                                 "attributeId");
+               if (((*names)[p] == NULL) || ((*OIDs_out)[p] == NULL)) {
+                       status = ADS_ERROR(LDAP_NO_MEMORY);
+                       goto out;
+               }
+
+               p++;
+       }
+
+       if (*count < num_OIDs) {
+               status = ADS_ERROR_NT(STATUS_SOME_UNMAPPED);
+               goto out;
+       }
+
+       status = ADS_ERROR(LDAP_SUCCESS);
+out:
+       ads_msgfree(ads, res);
+
+       return status;
+}
+
+const char *ads_get_attrname_by_oid(ADS_STRUCT *ads, const char *schema_path, TALLOC_CTX *mem_ctx, const char * OID)
+{
+       ADS_STATUS rc;
+       int count = 0;
+       void *res = NULL;
+       char *expr = NULL;
+       const char *attrs[] = { "lDAPDisplayName", NULL };
+       char *result;
+
+       if (ads == NULL || mem_ctx == NULL || OID == NULL) {
+               goto failed;
+       }
+
+       expr = talloc_asprintf(mem_ctx, "(attributeId=%s)", OID);
+       if (expr == NULL) {
+               goto failed;
+       }
+
+       rc = ads_do_search_retry(ads, schema_path, LDAP_SCOPE_SUBTREE, 
+               expr, attrs, &res);
+       if (!ADS_ERR_OK(rc)) {
+               goto failed;
+       }
+
+       count = ads_count_replies(ads, res);
+       if (count == 0 || !res) {
+               goto failed;
+       }
+
+       result = ads_pull_string(ads, mem_ctx, res, "lDAPDisplayName");
+       ads_msgfree(ads, res);
+
+       return result;
+       
+failed:
+       DEBUG(0,("ads_get_attrname_by_oid: failed to retrieve name for oid: %s\n", 
+               OID));
+       
+       ads_msgfree(ads, res);
+       return NULL;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **schema_path)
+{
+       ADS_STATUS status;
+       void *res;
+       const char *schema;
+       const char *attrs[] = { "schemaNamingContext", NULL };
+
+       status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
+       if ( (schema = ads_pull_string(ads, mem_ctx, res, "schemaNamingContext")) == NULL ) {
+               return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+       }
+
+       if ( (*schema_path = talloc_strdup(mem_ctx, schema)) == NULL ) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       ads_msgfree(ads, res);
+
+       return status;
+}
+
+/**
+ * Check for "Services for Unix" or rfc2307 Schema and load some attributes into the ADS_STRUCT
+ * @param ads connection to ads server
+ * @param enum mapping type
+ * @return BOOL status of search (False if one or more attributes couldn't be
+ * found in Active Directory)
+ **/ 
+ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping map_type) 
+{
+       TALLOC_CTX *ctx = NULL; 
+       ADS_STATUS status;
+       char **oids_out, **names_out;
+       size_t num_names;
+       char *schema_path = NULL;
+       ADS_STRUCT *ads_s = ads;
+       int i;
+
+       const char *oids_sfu[] = {      ADS_ATTR_SFU_UIDNUMBER_OID,
+                                       ADS_ATTR_SFU_GIDNUMBER_OID,
+                                       ADS_ATTR_SFU_HOMEDIR_OID,
+                                       ADS_ATTR_SFU_SHELL_OID,
+                                       ADS_ATTR_SFU_GECOS_OID};
+
+       const char *oids_rfc2307[] = {  ADS_ATTR_RFC2307_UIDNUMBER_OID,
+                                       ADS_ATTR_RFC2307_GIDNUMBER_OID,
+                                       ADS_ATTR_RFC2307_HOMEDIR_OID,
+                                       ADS_ATTR_RFC2307_SHELL_OID,
+                                       ADS_ATTR_RFC2307_GECOS_OID };
+
+       DEBUG(10,("ads_check_posix_schema_mapping\n"));
+
+       switch (map_type) {
+       
+               case WB_POSIX_MAP_TEMPLATE:
+               case WB_POSIX_MAP_UNIXINFO:
+                       DEBUG(10,("ads_check_posix_schema_mapping: nothing to do\n"));
+                       return ADS_ERROR(LDAP_SUCCESS);
+
+               case WB_POSIX_MAP_SFU:
+               case WB_POSIX_MAP_RFC2307:
+                       break;
+
+               default:
+                       DEBUG(0,("ads_check_posix_schema_mapping: "
+                                "unknown enum %d\n", map_type));
+                       return ADS_ERROR(LDAP_PARAM_ERROR);
+       }
+
+       ads->schema.posix_uidnumber_attr = NULL;
+       ads->schema.posix_gidnumber_attr = NULL;
+       ads->schema.posix_homedir_attr = NULL;
+       ads->schema.posix_shell_attr = NULL;
+       ads->schema.posix_gecos_attr = NULL;
+
+       ctx = talloc_init("ads_check_posix_schema_mapping");
+       if (ctx == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       /* establish a new ldap tcp session if necessary */
+
+       if (!ads->ld) {
+               if ((ads_s = ads_init(ads->server.realm, ads->server.workgroup, 
+                                     ads->server.ldap_server)) == NULL) {
+                       status = ADS_ERROR(LDAP_SERVER_DOWN);
+                       goto done;
+               }
+
+               ads_s->auth.flags = ADS_AUTH_ANON_BIND;
+               status = ads_connect(ads_s);
+               if (!ADS_ERR_OK(status)) {
+                       goto done;
+               }
+       }
+
+       status = ads_schema_path(ads, ctx, &schema_path);
+       if (!ADS_ERR_OK(status)) {
+               DEBUG(3,("ads_check_posix_mapping: Unable to retrieve schema DN!\n"));
+               goto done;
+       }
+
+       if (map_type == WB_POSIX_MAP_SFU) {
+               status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_sfu, 
+                                                  ARRAY_SIZE(oids_sfu), 
+                                                  &oids_out, &names_out, &num_names);
+       } else { 
+               status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_rfc2307, 
+                                                  ARRAY_SIZE(oids_rfc2307), 
+                                                  &oids_out, &names_out, &num_names);
+       }
+
+       if (!ADS_ERR_OK(status)) {
+               DEBUG(3,("ads_check_posix_schema_mapping: failed %s\n", 
+                       ads_errstr(status)));
+               goto done;
+       } 
+       
+       DEBUG(10,("ads_check_posix_schema_mapping: query succeeded, identified: %s\n",
+               wb_posix_map_str(map_type)));
+
+       for (i=0; i<num_names; i++) {
+
+               DEBUGADD(10,("\tOID %s has name: %s\n", oids_out[i], names_out[i]));
+
+               if (strequal(ADS_ATTR_RFC2307_UIDNUMBER_OID, oids_out[i]) ||
+                   strequal(ADS_ATTR_SFU_UIDNUMBER_OID, oids_out[i])) {
+                       ads->schema.posix_uidnumber_attr = SMB_STRDUP(names_out[i]);
+               }
+               if (strequal(ADS_ATTR_RFC2307_GIDNUMBER_OID, oids_out[i]) ||
+                   strequal(ADS_ATTR_SFU_GIDNUMBER_OID, oids_out[i])) {
+                       ads->schema.posix_gidnumber_attr = SMB_STRDUP(names_out[i]);
+               }
+               if (strequal(ADS_ATTR_RFC2307_HOMEDIR_OID, oids_out[i]) ||
+                   strequal(ADS_ATTR_SFU_HOMEDIR_OID, oids_out[i])) {
+                       ads->schema.posix_homedir_attr = SMB_STRDUP(names_out[i]);
+               }
+               if (strequal(ADS_ATTR_RFC2307_SHELL_OID, oids_out[i]) ||
+                   strequal(ADS_ATTR_SFU_SHELL_OID, oids_out[i])) {
+                       ads->schema.posix_shell_attr = SMB_STRDUP(names_out[i]);
+               }
+               if (strequal(ADS_ATTR_RFC2307_GECOS_OID, oids_out[i]) ||
+                   strequal(ADS_ATTR_SFU_GECOS_OID, oids_out[i])) {
+                       ads->schema.posix_gecos_attr = SMB_STRDUP(names_out[i]);
+               }
+       }
+
+       talloc_destroy(ctx);
+       
+       ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_uidnumber_attr);
+       ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_gidnumber_attr);
+       ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_homedir_attr);
+       ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_shell_attr);
+       ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_gecos_attr);
+       
+       status = ADS_ERROR(LDAP_SUCCESS);
+       
+       ads->schema.map_type = map_type;
+done:
+       /* free any temporary ads connections */
+       if (ads_s != ads) {
+               ads_destroy(&ads_s);
+       }
+       if (ctx) {
+               talloc_destroy(ctx);
+       }
+
+       return status;
+}
+
+#endif
index 6115af9d2f479c8376a298fc9d42ca6ca235cd95..3dc26f4cfa3a3eba9fbad9c5733c0e7a0c1b5f78 100644 (file)
@@ -38,6 +38,9 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
 {
        ADS_STRUCT *ads;
        ADS_STATUS status;
+       enum wb_posix_mapping map_type;
+
+       DEBUG(10,("ads_cached_connection\n"));
 
        if (domain->private_data) {
                ads = (ADS_STRUCT *)domain->private_data;
@@ -125,11 +128,18 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
                return NULL;
        }
 
-       if (use_nss_info("sfu") && (!ads_check_sfu_mapping(ads))) {
-               DEBUG(0,("ads_cached_connection: failed to check sfu attributes\n"));
-               return NULL;
-       }
+       map_type = get_nss_info(domain->name);
+
+       if ((map_type == WB_POSIX_MAP_RFC2307)||
+           (map_type == WB_POSIX_MAP_SFU)) {
        
+               status = ads_check_posix_schema_mapping(ads, map_type);
+               if (!ADS_ERR_OK(status)) {
+                       DEBUG(10,("ads_check_posix_schema_mapping failed "
+                                 "with: %s\n", ads_errstr(status)));
+               } 
+       }
+
        /* set the flag that says we don't own the memory even 
           though we do so that ads_destroy() won't destroy the 
           structure we pass back by reference */
@@ -155,6 +165,9 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
                               ADS_ATTR_SFU_HOMEDIR_OID, 
                               ADS_ATTR_SFU_SHELL_OID,
                               ADS_ATTR_SFU_GECOS_OID,
+                              ADS_ATTR_RFC2307_HOMEDIR_OID,
+                              ADS_ATTR_RFC2307_SHELL_OID,
+                              ADS_ATTR_RFC2307_GECOS_OID,
                               NULL};
        int i, count;
        ADS_STATUS rc;
@@ -208,13 +221,17 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
 
                name = ads_pull_username(ads, mem_ctx, msg);
 
-               if (use_nss_info("sfu")) {
+               if (get_nss_info(domain->name) && ads->schema.map_type) {
+
+                       DEBUG(10,("pulling posix attributes (%s schema)\n", 
+                               wb_posix_map_str(ads->schema.map_type)));
+
                        homedir = ads_pull_string(ads, mem_ctx, msg, 
-                                                 ads->schema.sfu_homedir_attr);
+                                                 ads->schema.posix_homedir_attr);
                        shell   = ads_pull_string(ads, mem_ctx, msg, 
-                                                 ads->schema.sfu_shell_attr);
+                                                 ads->schema.posix_shell_attr);
                        gecos   = ads_pull_string(ads, mem_ctx, msg, 
-                                                 ads->schema.sfu_gecos_attr);
+                                                 ads->schema.posix_gecos_attr);
                }
 
                if (gecos == NULL) {
@@ -446,6 +463,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
                               ADS_ATTR_SFU_HOMEDIR_OID, 
                               ADS_ATTR_SFU_SHELL_OID,
                               ADS_ATTR_SFU_GECOS_OID,
+                              ADS_ATTR_RFC2307_HOMEDIR_OID,
+                              ADS_ATTR_RFC2307_SHELL_OID,
+                              ADS_ATTR_RFC2307_GECOS_OID,
                               NULL};
        ADS_STATUS rc;
        int count;
@@ -484,13 +504,17 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
 
        info->acct_name = ads_pull_username(ads, mem_ctx, msg);
 
-       if (use_nss_info("sfu")) {
+       if (get_nss_info(domain->name) && ads->schema.map_type) {
+
+               DEBUG(10,("pulling posix attributes (%s schema)\n", 
+                       wb_posix_map_str(ads->schema.map_type)));
+               
                info->homedir   = ads_pull_string(ads, mem_ctx, msg, 
-                                                 ads->schema.sfu_homedir_attr);
+                                                 ads->schema.posix_homedir_attr);
                info->shell     = ads_pull_string(ads, mem_ctx, msg, 
-                                                 ads->schema.sfu_shell_attr);
+                                                 ads->schema.posix_shell_attr);
                info->full_name = ads_pull_string(ads, mem_ctx, msg,
-                                                 ads->schema.sfu_gecos_attr);
+                                                 ads->schema.posix_gecos_attr);
        }
 
        if (info->full_name == NULL) {
index 6179e497b787bfdcdedb64448f3c684a60cf9e18..07bd2a30bf721b386c6de89dd31a22b862d7cfec 100644 (file)
@@ -43,7 +43,7 @@ static BOOL fillup_pw_field(const char *lp_template,
        if (out == NULL)
                return False;
 
-       if (in && !strequal(in,"") && lp_security() == SEC_ADS && use_nss_info("sfu")) {
+       if (in && !strequal(in,"") && lp_security() == SEC_ADS && (get_nss_info(domname))) {
                safe_strcpy(out, in, sizeof(fstring) - 1);
                return True;
        }
index 0803f2a7abb0d04cab1a49edbe907cf26713583b..5edfad487d7d43130e31b191fc05ad7e4d880e74 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_IDMAP
 
-#ifndef ATTR_UIDNUMBER
-#define ATTR_UIDNUMBER ADS_ATTR_SFU_UIDNUMBER_OID
-#endif
-
-#ifndef ATTR_GIDNUMBER
-#define ATTR_GIDNUMBER ADS_ATTR_SFU_GIDNUMBER_OID
-#endif
-
 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
 
 NTSTATUS init_module(void);
@@ -48,28 +40,42 @@ static char *ad_idmap_uri = NULL;
 static char *attr_uidnumber = NULL;
 static char *attr_gidnumber = NULL;
 
-static BOOL ad_idmap_check_attr_mapping(ADS_STRUCT *ads)
+static ADS_STATUS ad_idmap_check_attr_mapping(ADS_STRUCT *ads)
 {
+       ADS_STATUS status;
+       enum wb_posix_mapping map_type;
+
        if (attr_uidnumber != NULL && attr_gidnumber != NULL) {
-               return True;
+               return ADS_ERROR(LDAP_SUCCESS);
        }
 
-       if (use_nss_info("sfu")) {
-       
-               if (!ads_check_sfu_mapping(ads)) {
-                       DEBUG(0,("ad_idmap_check_attr_mapping: failed to check for SFU schema\n"));
-                       return False;
-               }
+       SMB_ASSERT(ads->server.workgroup);
 
-               attr_uidnumber = SMB_STRDUP(ads->schema.sfu_uidnumber_attr);
-               attr_gidnumber = SMB_STRDUP(ads->schema.sfu_gidnumber_attr);
+       map_type = get_nss_info(ads->server.workgroup);
 
-       } else {
-               attr_uidnumber = SMB_STRDUP("uidNumber");
-               attr_gidnumber = SMB_STRDUP("gidNumber");
+       if ((map_type == WB_POSIX_MAP_SFU) ||
+           (map_type == WB_POSIX_MAP_RFC2307)) {
+
+               status = ads_check_posix_schema_mapping(ads, map_type);
+               if (ADS_ERR_OK(status)) {
+                       attr_uidnumber = SMB_STRDUP(ads->schema.posix_uidnumber_attr);
+                       attr_gidnumber = SMB_STRDUP(ads->schema.posix_gidnumber_attr);
+                       ADS_ERROR_HAVE_NO_MEMORY(attr_uidnumber);
+                       ADS_ERROR_HAVE_NO_MEMORY(attr_gidnumber);
+                       return ADS_ERROR(LDAP_SUCCESS);
+               } else {
+                       DEBUG(0,("ads_check_posix_schema_mapping failed: %s\n", ads_errstr(status)));
+                       /* return status; */
+               }
        }
+       
+       /* fallback to XAD defaults */
+       attr_uidnumber = SMB_STRDUP("uidNumber");
+       attr_gidnumber = SMB_STRDUP("gidNumber");
+       ADS_ERROR_HAVE_NO_MEMORY(attr_uidnumber);
+       ADS_ERROR_HAVE_NO_MEMORY(attr_gidnumber);
 
-       return True;
+       return ADS_ERROR(LDAP_SUCCESS);
 }
 
 static ADS_STRUCT *ad_idmap_cached_connection(void)
@@ -123,7 +129,8 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
 
        ads->is_mine = False;
 
-       if (!ad_idmap_check_attr_mapping(ads)) {
+       status = ad_idmap_check_attr_mapping(ads);
+       if (!ADS_ERR_OK(status)) {
                DEBUG(1, ("ad_idmap_init: failed to check attribute mapping\n"));
                return NULL;
        }
@@ -168,14 +175,14 @@ static NTSTATUS ad_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type)
                case ID_USERID:
                        if (asprintf(&expr, "(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d))(%s=%d))",
                                ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
-                               ATTR_UIDNUMBER, (int)unid.uid) == -1) {
+                               ads->schema.posix_uidnumber_attr, (int)unid.uid) == -1) {
                                return NT_STATUS_NO_MEMORY;
                        }
                        break;
                case ID_GROUPID:
                        if (asprintf(&expr, "(&(|(sAMAccountType=%d)(sAMAccountType=%d))(%s=%d))",
                                ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP,
-                               ATTR_GIDNUMBER, (int)unid.gid) == -1) {
+                               ads->schema.posix_gidnumber_attr, (int)unid.gid) == -1) {
                                return NT_STATUS_NO_MEMORY;
                        }
                        break;
@@ -228,7 +235,11 @@ static NTSTATUS ad_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_S
 {
        ADS_STATUS rc;
        NTSTATUS status = NT_STATUS_NONE_MAPPED;
-       const char *attrs[] = { "sAMAccountType", ATTR_UIDNUMBER, ATTR_GIDNUMBER, NULL };
+       const char *attrs[] = { "sAMAccountType", ADS_ATTR_SFU_UIDNUMBER_OID, 
+                                                 ADS_ATTR_SFU_GIDNUMBER_OID, 
+                                                 ADS_ATTR_RFC2307_UIDNUMBER_OID,
+                                                 ADS_ATTR_RFC2307_GIDNUMBER_OID,
+                                                 NULL };
        void *res = NULL;
        void *msg = NULL;
        char *expr = NULL;
index 7233cb48cd1ef34fd5a94bc101af3e24634d5b72..f78d3bdc2337b969c9969d740a729966970010b5 100644 (file)
@@ -110,17 +110,3 @@ NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, uint32 flags)
 
        return ret;
 }
-
-/* placeholder for checking lp_winbind_nss_info() */
-BOOL use_nss_info(const char *info)
-{
-       int i;
-       const char **list = lp_winbind_nss_info();
-
-       for (i=0; list[i]; i++) {
-               if (strequal(list[i], info))
-                       return True;
-       }
-
-       return False;
-}
diff --git a/source3/sam/nss_info.c b/source3/sam/nss_info.c
new file mode 100644 (file)
index 0000000..3d0e658
--- /dev/null
@@ -0,0 +1,111 @@
+/* 
+   Unix SMB/CIFS implementation.
+   nss info helpers
+   Copyright (C) Guenther Deschner 2006
+
+   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 2 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, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+/* winbind nss info = rfc2307 SO36:sfu FHAIN:rfc2307 PANKOW:template
+ *
+ * syntax is:
+ *     1st param: default setting
+ *     following ":" separated list elements:
+ *             DOMAIN:setting
+ *     setting can be one of "sfu", "rfc2307", "template", "unixinfo"
+ */
+
+enum wb_posix_mapping get_nss_info(const char *domain_name)
+{
+       const char **list = lp_winbind_nss_info();
+       enum wb_posix_mapping map_templ = WB_POSIX_MAP_TEMPLATE;
+       int i;
+
+       DEBUG(11,("get_nss_info for %s\n", domain_name));
+
+       if (!lp_winbind_nss_info() || !*lp_winbind_nss_info()) {
+               return WB_POSIX_MAP_TEMPLATE;
+       }
+
+       if ((map_templ = wb_posix_map_type(list[0])) == -1) {
+               DEBUG(0,("get_nss_info: invalid setting: %s\n", list[0]));
+               return WB_POSIX_MAP_TEMPLATE;
+       }
+
+       DEBUG(11,("get_nss_info: using \"%s\" by default\n", list[0]));
+
+       for (i=0; list[i]; i++) {
+
+               const char *p = list[i];
+               fstring tok;
+
+               if (!next_token(&p, tok, ":", sizeof(tok))) {
+                       DEBUG(0,("get_nss_info: no \":\" delimitier found\n"));
+                       continue;
+               }
+
+               if (strequal(tok, domain_name)) {
+               
+                       enum wb_posix_mapping type;
+                       
+                       if ((type = wb_posix_map_type(p)) == -1) {
+                               DEBUG(0,("get_nss_info: invalid setting: %s\n", p));
+                               /* return WB_POSIX_MAP_TEMPLATE; */
+                               continue;
+                       }
+
+                       DEBUG(11,("get_nss_info: using \"%s\" for domain: %s\n", p, tok));
+                       
+                       return type;
+               }
+       }
+
+       return map_templ;
+}
+
+const char *wb_posix_map_str(enum wb_posix_mapping mtype)
+{
+       switch (mtype) {
+               case WB_POSIX_MAP_TEMPLATE:
+                       return "template";
+               case WB_POSIX_MAP_SFU:
+                       return "sfu";
+               case WB_POSIX_MAP_RFC2307:
+                       return "rfc2307";
+               case WB_POSIX_MAP_UNIXINFO:
+                       return "unixinfo";
+               default:
+                       break;
+       }
+       return NULL;
+}
+
+enum wb_posix_mapping wb_posix_map_type(const char *map_str)
+{
+       if (strequal(map_str, "template")) 
+               return WB_POSIX_MAP_TEMPLATE;
+       else if (strequal(map_str, "sfu"))
+               return WB_POSIX_MAP_SFU;
+       else if (strequal(map_str, "rfc2307"))
+               return WB_POSIX_MAP_RFC2307;
+       else if (strequal(map_str, "unixinfo"))
+               return WB_POSIX_MAP_UNIXINFO;
+       
+       return -1;
+}