Index: include/ads.h =================================================================== --- include/ads.h (revision 15461) +++ include/ads.h (working copy) @@ -44,11 +44,12 @@ /* 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; + BOOL mapped_attrs; + char *posix_homedir_attr; + char *posix_shell_attr; + char *posix_uidnumber_attr; + char *posix_gidnumber_attr; + char *posix_gecos_attr; } schema; } ADS_STRUCT; @@ -102,6 +103,13 @@ #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" @@ -282,3 +298,10 @@ #endif } smb_krb5_addresses; #endif + +enum ads_posix_mapping { + ADS_POSIX_MAP_DEFAULT = 0, + ADS_POSIX_MAP_SFU = 1, + ADS_POSIX_MAP_RFC2307 = 2 +}; + Index: libads/ldap.c =================================================================== --- libads/ldap.c (revision 15461) +++ libads/ldap.c (working copy) @@ -2463,7 +2528,90 @@ return timegm(&tm); } +NTSTATUS ads_get_attrnames_by_oids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, + const char **OIDs, size_t num_OIDs, + char ***OIDs_out, char ***names, size_t *count) +{ + ADS_STATUS rc; + void *res = NULL; + LDAPMessage *msg; + NTSTATUS status; + char *expr = NULL; + const char *attrs[] = { "lDAPDisplayName", "attributeId", NULL }; + int i = 0, p = 0; + + if (!ads || !mem_ctx || !names || !count || !OIDs || !OIDs_out) { + return NT_STATUS_INVALID_PARAMETER; + } + if (num_OIDs == 0 || OIDs[0] == NULL) { + return NT_STATUS_NONE_MAPPED; + } + + if ((expr = talloc_asprintf(mem_ctx, "(|")) == NULL) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0; iconfig.schema_path, + LDAP_SCOPE_SUBTREE, expr, attrs, &res); + if (!ADS_ERR_OK(rc)) { + return NT_STATUS_UNSUCCESSFUL; /* FIXME */ + } + + *count = ads_count_replies(ads, res); + if (*count == 0 || !res) { + status = NT_STATUS_NONE_MAPPED; + goto out; + } + + if (((*names) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + if (((*OIDs_out) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) { + status = NT_STATUS_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 = NT_STATUS_NO_MEMORY; + goto out; + } + + p++; + } + + if (*count < num_OIDs) { + status = STATUS_SOME_UNMAPPED; + goto out; + } + + status = NT_STATUS_OK; +out: + ads_msgfree(ads, res); + + return status; +} + const char *ads_get_attrname_by_oid(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char * OID) { ADS_STATUS rc; @@ -2607,47 +2755,96 @@ } /** - * Check for "Services for Unix"-Schema and load some attributes into the ADS_STRUCT + * 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) **/ -BOOL ads_check_sfu_mapping(ADS_STRUCT *ads) -{ +BOOL ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum ads_posix_mapping map_type) +{ BOOL ret = False; TALLOC_CTX *ctx = NULL; const char *gidnumber, *uidnumber, *homedir, *shell, *gecos; + NTSTATUS status; + 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 }; + char **oids_out, **names_out; + size_t num_names; - ctx = talloc_init("ads_check_sfu_mapping"); - if (ctx == NULL) - goto done; + DEBUG(10,("ads_check_posix_schema_mapping\n")); - gidnumber = ads_get_attrname_by_oid(ads, ctx, ADS_ATTR_SFU_GIDNUMBER_OID); - if (gidnumber == NULL) - goto done; - ads->schema.sfu_gidnumber_attr = SMB_STRDUP(gidnumber); + switch (map_type) { + case ADS_POSIX_MAP_DEFAULT: + DEBUG(10,("ads_check_posix_schema_mapping: nothing to do\n")); + return True; + case ADS_POSIX_MAP_SFU: + case ADS_POSIX_MAP_RFC2307: + break; + default: + DEBUG(0,("ads_check_posix_schema_mapping: " + "unknown enum %d\n", map_type)); + return False; + } - uidnumber = ads_get_attrname_by_oid(ads, ctx, ADS_ATTR_SFU_UIDNUMBER_OID); - if (uidnumber == NULL) + ads->schema.posix_uidnumber_attr = NULL; + + ctx = talloc_init("ads_check_posix_schema_mapping"); + if (ctx == NULL) { goto done; - ads->schema.sfu_uidnumber_attr = SMB_STRDUP(uidnumber); + } - homedir = ads_get_attrname_by_oid(ads, ctx, ADS_ATTR_SFU_HOMEDIR_OID); - if (homedir == NULL) + if (map_type == ADS_POSIX_MAP_SFU) { + status = ads_get_attrnames_by_oids(ads, ctx, oids_sfu, ARRAY_SIZE(oids_sfu), + &oids_out, &names_out, &num_names); + } else { + status = ads_get_attrnames_by_oids(ads, ctx, oids_rfc2307, ARRAY_SIZE(oids_rfc2307), + &oids_out, &names_out, &num_names); + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3,("ads_check_posix_schema_mapping: failed %s\n", nt_errstr(status))); goto done; - ads->schema.sfu_homedir_attr = SMB_STRDUP(homedir); + } - shell = ads_get_attrname_by_oid(ads, ctx, ADS_ATTR_SFU_SHELL_OID); - if (shell == NULL) - goto done; - ads->schema.sfu_shell_attr = SMB_STRDUP(shell); + DEBUG(10,("ads_check_posix_schema_mapping: query succeeded\n")); - gecos = ads_get_attrname_by_oid(ads, ctx, ADS_ATTR_SFU_GECOS_OID); - if (gecos == NULL) - goto done; - ads->schema.sfu_gecos_attr = SMB_STRDUP(gecos); + for (i=0; ischema.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]); + } + } + + ads->schema.mapped_attrs = ret = True; done: if (ctx) talloc_destroy(ctx); Index: nsswitch/winbindd_ads.c =================================================================== --- nsswitch/winbindd_ads.c (revision 15461) +++ nsswitch/winbindd_ads.c (working copy) @@ -125,10 +125,7 @@ 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; - } + ads_check_posix_schema_mapping(ads, get_nss_info()); /* set the flag that says we don't own the memory even though we do so that ads_destroy() won't destroy the @@ -155,6 +152,9 @@ 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 +208,16 @@ name = ads_pull_username(ads, mem_ctx, msg); - if (use_nss_info("sfu")) { + if (get_nss_info() && ads->schema.mapped_attrs) { + + DEBUG(10,("pulling posix attributes\n")); + 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 +449,9 @@ 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 +490,16 @@ info->acct_name = ads_pull_username(ads, mem_ctx, msg); - if (use_nss_info("sfu")) { + if (get_nss_info() && ads->schema.mapped_attrs) { + + DEBUG(10,("pulling posix attributes\n")); + 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: nsswitch/winbindd_user.c =================================================================== --- nsswitch/winbindd_user.c (revision 15461) +++ nsswitch/winbindd_user.c (working copy) @@ -43,7 +43,7 @@ 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())) { safe_strcpy(out, in, sizeof(fstring) - 1); return True; } Index: sam/idmap_util.c =================================================================== --- sam/idmap_util.c (revision 15461) +++ sam/idmap_util.c (working copy) @@ -124,3 +124,22 @@ return False; } + +enum ads_posix_mapping get_nss_info(void) +{ + const char **list = lp_winbind_nss_info(); + + if (!lp_winbind_nss_info() || !*lp_winbind_nss_info()) { + return ADS_POSIX_MAP_DEFAULT; + } + + if (strequal(list[0], "sfu")) { + return ADS_POSIX_MAP_SFU; + } + + if (strequal(list[0], "rfc2307")) { + return ADS_POSIX_MAP_RFC2307; + } + + return ADS_POSIX_MAP_DEFAULT; +} Index: sam/idmap_ad.c =================================================================== --- sam/idmap_ad.c (revision 15461) +++ sam/idmap_ad.c (working copy) @@ -54,16 +54,9 @@ return True; } - 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; - } - - attr_uidnumber = SMB_STRDUP(ads->schema.sfu_uidnumber_attr); - attr_gidnumber = SMB_STRDUP(ads->schema.sfu_gidnumber_attr); - + if (ads_check_posix_schema_mapping(ads, get_nss_info())) { + attr_uidnumber = SMB_STRDUP(ads->schema.posix_uidnumber_attr); + attr_gidnumber = SMB_STRDUP(ads->schema.posix_gidnumber_attr); } else { attr_uidnumber = SMB_STRDUP("uidNumber"); attr_gidnumber = SMB_STRDUP("gidNumber");