--- samba-3.0.23/source/sam/idmap_ad.c.multiple_connections 2006-05-23 19:54:34.000000000 +0100 +++ samba-3.0.23/source/sam/idmap_ad.c 2006-05-30 15:07:36.000000000 +0100 @@ -26,6 +26,7 @@ */ #include "includes.h" +#include "../nsswitch/winbindd.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_IDMAP @@ -34,58 +35,78 @@ NTSTATUS init_module(void); -static ADS_STRUCT *ad_idmap_ads = NULL; -static char *ad_idmap_uri = NULL; +/* + * Connection management. + * + * Like winbindd_ads.c, use a separate connection to each domain. + * FIXME: Merge this with the code there? + */ -static char *attr_uidnumber = NULL; -static char *attr_gidnumber = NULL; +/* + * Create a new connection for the cache. This ought to be the same as code in + * winbindd_ads but I have factored out the domain->private_data checking. So the + * code here is simply an edited version of the original from idmap_ad.c + */ -static ADS_STATUS ad_idmap_check_attr_mapping(ADS_STRUCT *ads) +static ADS_STRUCT *ad_idmap_new_cached_connection(struct winbindd_domain *domain) { + ADS_STRUCT *ads = NULL; ADS_STATUS status; - enum wb_posix_mapping map_type; - if (attr_uidnumber != NULL && attr_gidnumber != NULL) { - return ADS_ERROR(LDAP_SUCCESS); + DEBUG(3,("ad_idmap_new_cached_connection to %s [%s]\n", + domain->name, sid_string_static(&domain->sid))); + + SMB_ASSERT(domain->private_data == NULL); + + /* we don't want this to affect the users ccache */ + setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1); + + ads = ads_init(domain->alt_name, domain->name, NULL); + if (!ads) { + DEBUG(1,("ads_init failed\n")); + return NULL; } - SMB_ASSERT(ads->server.workgroup); + /* the machine acct password might have change - fetch it every time */ + SAFE_FREE(ads->auth.password); + ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); - map_type = get_nss_info(ads->server.workgroup); + /* FIXME? This looks like a significant different between pre1 and rc1 */ - if ((map_type == WB_POSIX_MAP_SFU) || - (map_type == WB_POSIX_MAP_RFC2307)) { + SAFE_FREE(ads->auth.realm); + ads->auth.realm = SMB_STRDUP(lp_realm()); - 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; */ - } + status = ads_connect(ads); + if (!ADS_ERR_OK(status)) { + DEBUG(1, ("ad_idmap_new_cached_connection: failed to connect to AD %s\n", + domain->name)); + ads_destroy(&ads); + return NULL; + } + + status = ads_check_posix_schema_mapping(ads, get_nss_info(domain->name)); + if (!ADS_ERR_OK(status)) { + DEBUG(1,("ad_idmap_new_cached_connection: ads_check_posix_schema_mapping failed for %s with %s\n", + domain->name,ads_errstr(status))); + + ads_destroy(&ads); + return NULL; } - - /* 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 ADS_ERROR(LDAP_SUCCESS); + ads->is_mine = False; + + domain->private_data = ads; + return ads; } -static ADS_STRUCT *ad_idmap_cached_connection(void) +static ADS_STRUCT *ad_idmap_live_connection(struct winbindd_domain *d) { - ADS_STRUCT *ads; - ADS_STATUS status; - BOOL local = False; + ADS_STRUCT *ads = (ADS_STRUCT *) d->private_data; - if (ad_idmap_ads != NULL) { - ads = ad_idmap_ads; + if (ads) { + + DEBUG(7,("Found cached connection to realm %s for [%s]\n", + ads->server.realm, sid_string_static(&d->sid))); /* check for a valid structure */ @@ -93,63 +114,54 @@ (uint32) ads->auth.expire, (uint32) time(NULL))); if ( ads->config.realm && (ads->auth.expire > time(NULL))) { return ads; - } else { - /* we own this ADS_STRUCT so make sure it goes away */ - ads->is_mine = True; - ads_destroy( &ads ); - ads_kdestroy(WINBIND_CCACHE_NAME); - ad_idmap_ads = NULL; } - } - if (!local) { - /* we don't want this to affect the users ccache */ - setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1); - } + /* tickets have expired so we need a new connection */ + /* we own this ADS_STRUCT so make sure it goes away */ - ads = ads_init(lp_realm(), lp_workgroup(), NULL); - if (!ads) { - DEBUG(1,("ads_init failed\n")); - return NULL; + ads->is_mine = True; + ads_destroy( &ads ); + ads_kdestroy(WINBIND_CCACHE_NAME); + ads = NULL; + d->private_data = NULL; } - /* the machine acct password might have change - fetch it every time */ - SAFE_FREE(ads->auth.password); - ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + return ad_idmap_new_cached_connection(d); +} - SAFE_FREE(ads->auth.realm); - ads->auth.realm = SMB_STRDUP(lp_realm()); +static ADS_STRUCT *ad_idmap_cached_connection(const DOM_SID *sid) +{ + struct winbindd_domain *d; + ADS_STRUCT *ads = NULL; - status = ads_connect(ads); - if (!ADS_ERR_OK(status)) { - DEBUG(1, ("ad_idmap_init: failed to connect to AD\n")); - ads_destroy(&ads); + d = find_domain_from_sid(sid); + + if (d == NULL) { + DEBUG(1,("Tried to find connection to unknown domain [%s]\n", + sid_string_static(sid))); return NULL; } - ads->is_mine = False; - - status = ad_idmap_check_attr_mapping(ads); - if (!ADS_ERR_OK(status)) { - DEBUG(1, ("ad_idmap_init: failed to check attribute mapping\n")); + if (!d->active_directory) { + DEBUG(1,("ad_idmap_cached_connection found non-AD domain %s\n", + d->name)); return NULL; } - ad_idmap_ads = ads; - return ads; + return ad_idmap_live_connection(d); } + static NTSTATUS ad_idmap_init(char *uri) { - ad_idmap_uri = SMB_STRDUP(uri); - if (ad_idmap_uri == NULL) { - return NT_STATUS_NO_MEMORY; + if (*uri) { + DEBUG(0,("Warning: idmap_ad no longer supports a URI (%s)\n",uri)); } return NT_STATUS_OK; } -static NTSTATUS ad_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type) +static NTSTATUS ad_idmap_get_sid_from_id_in_domain(ADS_STRUCT *ads,DOM_SID *sid, unid_t unid, int id_type) { ADS_STATUS rc; NTSTATUS status = NT_STATUS_NONE_MAPPED; @@ -159,18 +171,11 @@ char *expr = NULL; fstring sid_string; int count; - ADS_STRUCT *ads; if (sid == NULL) { return NT_STATUS_INVALID_PARAMETER; } - ads = ad_idmap_cached_connection(); - if (ads == NULL) { - DEBUG(1, ("ad_idmap_get_id_from_sid ADS uninitialized\n")); - return NT_STATUS_NOT_SUPPORTED; - } - switch (id_type & ID_TYPEMASK) { case ID_USERID: if (asprintf(&expr, "(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d))(%s=%d))", @@ -231,6 +236,33 @@ return status; } + +/* + * Scan all known domains to try to map an id into a sid + */ + +static NTSTATUS ad_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type) +{ + struct winbindd_domain *d; + ADS_STRUCT *ads; + NTSTATUS status; + + for (d = domain_list(); d; d = d->next) { + ads = ad_idmap_live_connection(d); + if (!ads) { + DEBUG(1,("ad_idmap_get_sid_from_id: could not check %s\n", + d->name)); + continue; + } + + status = ad_idmap_get_sid_from_id_in_domain(ads,sid,unid,id_type); + if (NT_STATUS_IS_OK(status)) + return status; + } + + return NT_STATUS_UNSUCCESSFUL; +} + static NTSTATUS ad_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_SID *sid) { ADS_STATUS rc; @@ -249,13 +281,14 @@ int count; ADS_STRUCT *ads; - if (unid == NULL) { + if ((unid == NULL) || (sid == NULL)) { return NT_STATUS_INVALID_PARAMETER; } - ads = ad_idmap_cached_connection(); + ads = ad_idmap_cached_connection(sid); if (ads == NULL) { - DEBUG(1, ("ad_idmap_get_id_from_sid ADS uninitialized\n")); + DEBUG(1, ("ad_idmap_get_id_from_sid [%s] could not get connection\n", + sid_string_static(sid))); return NT_STATUS_NOT_SUPPORTED; } @@ -309,9 +342,9 @@ break; } - if (!ads_pull_uint32(ads, msg, (*id_type == ID_GROUPID) ? attr_gidnumber : attr_uidnumber, &uid)) { + if (!ads_pull_uint32(ads, msg, (*id_type == ID_GROUPID) ? ads->schema.posix_gidnumber_attr : ads->schema.posix_uidnumber_attr, &uid)) { DEBUG(1, ("ad_idmap_get_id_from_sid: ads_pull_uint32: could not read attribute '%s'\n", - (*id_type == ID_GROUPID) ? attr_gidnumber : attr_uidnumber)); + (*id_type == ID_GROUPID) ? ads->schema.posix_gidnumber_attr : ads->schema.posix_uidnumber_attr)); goto done; } @@ -341,17 +374,7 @@ static NTSTATUS ad_idmap_close(void) { - ADS_STRUCT *ads = ad_idmap_ads; - - if (ads != NULL) { - /* we own this ADS_STRUCT so make sure it goes away */ - ads->is_mine = True; - ads_destroy( &ads ); - ad_idmap_ads = NULL; - } - - SAFE_FREE(attr_uidnumber); - SAFE_FREE(attr_gidnumber); + /* We might not own all those connections, so don't mess with them */ return NT_STATUS_OK; } @@ -380,6 +403,7 @@ /* support for new authentication subsystem */ NTSTATUS init_module(void) { + DEBUG(1,("idmap_ad: This version has the multiple-connection patch\n")); return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ad", &ad_methods); }