Foreign Principal Mapping

Benjamin Bennett ben at phys.psu.edu
Sat Oct 18 13:47:15 GMT 2003


Hi Folks,
   This is a patch which will allow a samba system acting as a Win2k 
domain member to use the kerberos user mappings in AD.

   So, say you have a samba box as a member of the Win2k domain 'MS'. 
That domain trusts the kerberos realm 'MIT'. If you present a tkt as 
joe at MIT to the samba system, it will lookup a matching 
altSecurityIdentities attribute in AD for the MS domain, and if found 
you are now joe.schmoe at MS or whatever account it got matched to.

   Thanks for all the good work in 3! What it and this patch provide, 
I've been waiting about 2.5yrs to be able to do.

--ben


--- samba-3.0.0/source/libads/ads_ldap.c	2003-07-01 16:44:25.000000000 -0400
+++ samba-3.0.0-ben/source/libads/ads_ldap.c	2003-10-18 
08:05:23.000000000 -0400
@@ -152,4 +152,92 @@
  	return status;
  }

+NTSTATUS ads_map_foreign_principal(const char *foreign, char **local)
+{
+	const char *attrs[] = {"userPrincipalName", NULL};
+	int count;
+	ADS_STRUCT *ads = NULL;
+	ADS_STATUS rc;
+	TALLOC_CTX *ctx = NULL;
+	void *res = NULL;
+	char *ldap_exp = NULL;
+	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+	char *escaped_foreign = NULL;
+	char *local_ctx = NULL;
+
+	ads = ads_init(lp_realm(), NULL, NULL);
+	if (!ads) {
+		DEBUG(1,("ads_map_foreign_principal: ads_init for %s failed!\n", 
lp_realm()));
+		goto done;
+	}
+
+	SAFE_FREE(ads->auth.password);
+	SAFE_FREE(ads->auth.realm);
+	ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), 
NULL, NULL);
+	ads->auth.realm = strdup(lp_realm());
+	if(!ADS_ERR_OK(ads_connect(ads)) || !ads->config.realm) {
+		DEBUG(1,("ads_map_foreign_principal: ads_connect failed!\n"));
+		goto done;
+	}
+
+	if(!(ctx = talloc_init("ads_map_foreign_principal"))){
+		DEBUG(1,("ads_map_foreign_principal: talloc_init failed!\n"));
+		status = NT_STATUS_NO_MEMORY;
+		goto done;
+	}
+
+	escaped_foreign = escape_ldap_string_alloc(foreign);
+	if (!escaped_foreign) {
+		DEBUG(1,("ads_map_foreign_principal: escape_ldap_string_alloc 
failed!\n"));
+		status = NT_STATUS_NO_MEMORY;
+		goto done;
+	}
+
+	if (!asprintf(&ldap_exp, "(altSecurityIdentities=Kerberos:%s)",
+			escaped_foreign) == -1) {
+		DEBUG(1,("ads_map_foreign_principal: asprintf failed!\n"));
+		status = NT_STATUS_NO_MEMORY;
+		goto done;
+	}
+
+	DEBUG(5,("ads_map_foreign_principal ads_search_retry: %s\n", ldap_exp));
+	rc = ads_search_retry(ads, &res, ldap_exp, attrs);
+	SAFE_FREE(ldap_exp);
+	if (!ADS_ERR_OK(rc)) {
+		DEBUG(1,("ads_map_foreign_principal ads_search_retry: %s\n", 
ads_errstr(rc)));
+		goto done;
+	}
+
+	count = ads_count_replies(ads, res);
+	if (count != 1) {
+		DEBUG(3,("ads_map_foreign_principal ads_search_retry: %s had %d 
matches\n", foreign, count));
+		goto done;
+	}
+
+	local_ctx = ads_pull_string(ads, ctx, res, "userPrincipalName");
+	if (!local_ctx) {
+		DEBUG(1,("ads_map_foreign_principal: No userPrincipalName for %s\n", 
foreign));
+		goto done;
+	}
+
+	if (!asprintf(local, "%s", local_ctx) == -1) {
+		DEBUG(1,("ads_map_foreign_principal: asprintf failed!\n"));
+		status = NT_STATUS_NO_MEMORY;
+		goto done;
+	}
+
+	status = NT_STATUS_OK;
+
+done:
+	DEBUG(5,("ads_map_foreign_principal: cleaning up\n"));
+
+        SAFE_FREE(escaped_foreign);
+	if (res) ads_msgfree(ads, res);
+	if (ads) ads_destroy(&ads);
+	if (ctx) talloc_destroy(ctx);
+
+	DEBUG(5,("ads_map_foreign_principal: returning\n"));
+	return status;
+}
+
  #endif
--- samba-3.0.0/source/smbd/sesssetup.c	2003-08-28 17:42:45.000000000 -0400
+++ samba-3.0.0-ben/source/smbd/sesssetup.c	2003-10-18 
09:08:27.000000000 -0400
@@ -194,6 +194,23 @@
  			return ERROR_NT(NT_STATUS_LOGON_FAILURE);
  		}
  		foreign = True;
+
+		if (lp_allow_trusted_domains()) {
+			char *local_principal = NULL;
+			char *foreign_principal = NULL;
+			asprintf(&foreign_principal, "%s@%s", client, p+1);
+			
+			ret = ads_map_foreign_principal(foreign_principal, &local_principal);
+			if (NT_STATUS_IS_OK(ret)) {
+				DEBUG(1,("Mapping %s to %s\n", foreign_principal, local_principal));
+				SAFE_FREE(client);
+				client = local_principal;
+				p = strchr_m(client, '@');
+				*p = 0;
+				foreign = False;
+			}
+			SAFE_FREE(foreign_principal);
+		}
  	}

  	/* this gives a fully qualified user name (ie. with full realm).





More information about the samba-technical mailing list