diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/Makefile.in | 3 | ||||
-rw-r--r-- | source3/include/ads.h | 32 | ||||
-rw-r--r-- | source3/libads/ads_struct.c | 10 | ||||
-rw-r--r-- | source3/libads/ldap.c | 150 | ||||
-rw-r--r-- | source3/libads/ldap_schema.c | 329 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_ads.c | 48 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_user.c | 2 | ||||
-rw-r--r-- | source3/sam/idmap_ad.c | 63 | ||||
-rw-r--r-- | source3/sam/idmap_util.c | 14 | ||||
-rw-r--r-- | source3/sam/nss_info.c | 111 |
10 files changed, 548 insertions, 214 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 9ff74f60b8..25927be3ef 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -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 diff --git a/source3/include/ads.h b/source3/include/ads.h index 48b9bbffa0..e93d36a5ca 100644 --- a/source3/include/ads.h +++ b/source3/include/ads.h @@ -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" diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c index 48533c7ffb..e546f2ae8a 100644 --- a/source3/libads/ads_struct.c +++ b/source3/libads/ads_struct.c @@ -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); diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index b208e58504..4a14527a22 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -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 index 0000000000..a0c735208f --- /dev/null +++ b/source3/libads/ldap_schema.c @@ -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 diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index 6115af9d2f..3dc26f4cfa 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -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) { diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index 6179e497b7..07bd2a30bf 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -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; } diff --git a/source3/sam/idmap_ad.c b/source3/sam/idmap_ad.c index 0803f2a7ab..5edfad487d 100644 --- a/source3/sam/idmap_ad.c +++ b/source3/sam/idmap_ad.c @@ -30,14 +30,6 @@ #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; diff --git a/source3/sam/idmap_util.c b/source3/sam/idmap_util.c index 7233cb48cd..f78d3bdc23 100644 --- a/source3/sam/idmap_util.c +++ b/source3/sam/idmap_util.c @@ -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 index 0000000000..3d0e658a35 --- /dev/null +++ b/source3/sam/nss_info.c @@ -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; +} |