1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

s3:winbindd: use winbindd_get_trust_credentials()/ads_connect_creds() in winbindd_ads.c

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
Stefan Metzmacher 2024-02-27 09:44:19 +01:00
parent 8166642e1b
commit f903d80769

View File

@ -44,8 +44,6 @@
extern struct winbindd_methods reconnect_methods;
extern struct winbindd_methods msrpc_methods;
#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
/**
* Check if cached connection can be reused. If the connection cannot
* be reused the ADS_STRUCT is freed and the pointer is set to NULL.
@ -69,49 +67,77 @@ static void ads_cached_connection_reuse(ADS_STRUCT **adsp)
return;
} else {
/* we own this ADS_STRUCT so make sure it goes away */
DEBUG(7,("Deleting expired krb5 credential cache\n"));
DEBUG(7,("Deleting expired ads struct\n"));
TALLOC_FREE(ads);
ads_kdestroy(WINBIND_CCACHE_NAME);
*adsp = NULL;
}
}
}
static NTSTATUS ads_cached_connection_reconnect_creds(struct ads_struct *ads,
void *private_data,
TALLOC_CTX *mem_ctx,
struct cli_credentials **creds)
{
struct winbindd_domain *target_domain = NULL;
if (ads->server.realm != NULL) {
target_domain = find_domain_from_name_noinit(ads->server.realm);
}
if (target_domain == NULL && ads->server.workgroup != NULL) {
target_domain = find_domain_from_name_noinit(ads->server.workgroup);
}
if (target_domain == NULL) {
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
return winbindd_get_trust_credentials(target_domain,
mem_ctx,
false, /* netlogon */
false, /* ipc_fallback */
creds);
}
/**
* @brief Establish a connection to a DC
*
* @param[out] adsp ADS_STRUCT that will be created
* @param[in] target_realm Realm of domain to connect to
* @param[in] target_dom_name 'workgroup' name of domain to connect to
* @param[in] target_domain target domain
* @param[in] ldap_server DNS name of server to connect to
* @param[in] password Our machine account secret
* @param[in] creds credentials to use
* @param[in] auth_realm Realm of local domain for creating krb token
*
* @return ADS_STATUS
*/
static ADS_STATUS ads_cached_connection_connect(const char *target_realm,
const char *target_dom_name,
static ADS_STATUS ads_cached_connection_connect(struct winbindd_domain *target_domain,
const char *ldap_server,
char *password,
char *auth_realm,
TALLOC_CTX *mem_ctx,
ADS_STRUCT **adsp)
{
TALLOC_CTX *tmp_ctx = talloc_stackframe();
const char *target_realm = target_domain->alt_name;
const char *target_dom_name = target_domain->name;
struct cli_credentials *creds = NULL;
ADS_STRUCT *ads;
ADS_STATUS status;
NTSTATUS ntstatus;
struct sockaddr_storage dc_ss;
fstring dc_name;
enum credentials_use_kerberos krb5_state;
if (auth_realm == NULL) {
TALLOC_FREE(tmp_ctx);
return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
/* the machine acct password might have change - fetch it every time */
ntstatus = winbindd_get_trust_credentials(target_domain,
tmp_ctx,
false, /* netlogon */
false, /* ipc_fallback */
&creds);
if (!NT_STATUS_IS_OK(ntstatus)) {
status = ADS_ERROR_NT(ntstatus);
goto out;
}
/* we don't want this to affect the users ccache */
setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
ads = ads_init(tmp_ctx,
target_realm,
target_dom_name,
@ -123,44 +149,14 @@ static ADS_STATUS ads_cached_connection_connect(const char *target_realm,
goto out;
}
ADS_TALLOC_CONST_FREE(ads->auth.password);
ADS_TALLOC_CONST_FREE(ads->auth.realm);
ads->auth.password = talloc_strdup(ads, password);
if (ads->auth.password == NULL) {
status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
goto out;
}
/* In FIPS mode, client use kerberos is forced to required. */
krb5_state = lp_client_use_kerberos();
switch (krb5_state) {
case CRED_USE_KERBEROS_REQUIRED:
ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
ads->auth.flags &= ~ADS_AUTH_ALLOW_NTLMSSP;
break;
case CRED_USE_KERBEROS_DESIRED:
ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
break;
case CRED_USE_KERBEROS_DISABLED:
ads->auth.flags |= ADS_AUTH_DISABLE_KERBEROS;
ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
break;
}
ads->auth.realm = talloc_asprintf_strupper_m(ads, "%s", auth_realm);
if (ads->auth.realm == NULL) {
status = ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
goto out;
}
ads_set_reconnect_fn(ads, ads_cached_connection_reconnect_creds, NULL);
/* Setup the server affinity cache. We don't reaally care
about the name. Just setup affinity and the KRB5_CONFIG
file. */
get_dc_name(ads->server.workgroup, ads->server.realm, dc_name, &dc_ss);
status = ads_connect(ads);
status = ads_connect_creds(ads, creds);
if (!ADS_ERR_OK(status)) {
DEBUG(1,("ads_connect for domain %s failed: %s\n",
target_dom_name, ads_errstr(status)));
@ -179,8 +175,6 @@ ADS_STATUS ads_idmap_cached_connection(const char *dom_name,
{
TALLOC_CTX *tmp_ctx = talloc_stackframe();
char *ldap_server = NULL;
char *realm = NULL;
char *password = NULL;
struct winbindd_domain *wb_dom = NULL;
ADS_STATUS status;
@ -212,55 +206,20 @@ ADS_STATUS ads_idmap_cached_connection(const char *dom_name,
wb_dom = find_domain_from_name(dom_name);
if (wb_dom == NULL) {
DBG_DEBUG("could not find domain '%s'\n", dom_name);
status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
goto out;
TALLOC_FREE(tmp_ctx);
return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
}
DBG_DEBUG("find_domain_from_name found realm '%s' for "
" domain '%s'\n", wb_dom->alt_name, dom_name);
if (!get_trust_pw_clear(dom_name, &password, NULL, NULL)) {
status = ADS_ERROR_NT(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
goto out;
}
if (IS_DC) {
SMB_ASSERT(wb_dom->alt_name != NULL);
realm = talloc_strdup(tmp_ctx, wb_dom->alt_name);
} else {
struct winbindd_domain *our_domain = wb_dom;
/* always give preference to the alt_name in our
primary domain if possible */
if (!wb_dom->primary) {
our_domain = find_our_domain();
}
if (our_domain->alt_name != NULL) {
realm = talloc_strdup(tmp_ctx, our_domain->alt_name);
} else {
realm = talloc_strdup(tmp_ctx, lp_realm());
}
}
if (realm == NULL) {
status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
goto out;
}
status = ads_cached_connection_connect(
wb_dom->alt_name, /* realm to connect to. */
dom_name, /* 'workgroup' name for ads_init */
wb_dom,
ldap_server, /* DNS name to connect to. */
password, /* password for auth realm. */
realm, /* realm used for krb5 ticket. */
mem_ctx, /* memory context for ads struct */
adsp); /* Returns ads struct. */
out:
TALLOC_FREE(tmp_ctx);
SAFE_FREE(password);
return status;
}
@ -274,8 +233,6 @@ static ADS_STATUS ads_cached_connection(struct winbindd_domain *domain,
{
TALLOC_CTX *tmp_ctx = talloc_stackframe();
ADS_STATUS status;
char *password = NULL;
char *realm = NULL;
if (IS_AD_DC) {
/*
@ -295,43 +252,9 @@ static ADS_STATUS ads_cached_connection(struct winbindd_domain *domain,
return ADS_SUCCESS;
}
/* the machine acct password might have change - fetch it every time */
if (!get_trust_pw_clear(domain->name, &password, NULL, NULL)) {
status = ADS_ERROR_NT(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
goto out;
}
if ( IS_DC ) {
SMB_ASSERT(domain->alt_name != NULL);
realm = talloc_strdup(tmp_ctx, domain->alt_name);
} else {
struct winbindd_domain *our_domain = domain;
/* always give preference to the alt_name in our
primary domain if possible */
if ( !domain->primary )
our_domain = find_our_domain();
if (our_domain->alt_name != NULL) {
realm = talloc_strdup(tmp_ctx, our_domain->alt_name );
} else {
realm = talloc_strdup(tmp_ctx, lp_realm() );
}
}
if (realm == NULL) {
status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
goto out;
}
status = ads_cached_connection_connect(
domain->alt_name,
domain->name, NULL,
password,
realm,
domain,
NULL,
domain,
&domain->backend_data.ads_conn);
if (!ADS_ERR_OK(status)) {
@ -344,15 +267,13 @@ static ADS_STATUS ads_cached_connection(struct winbindd_domain *domain,
domain->name);
domain->backend = &reconnect_methods;
}
goto out;
TALLOC_FREE(tmp_ctx);
return status;
}
*adsp = domain->backend_data.ads_conn;
out:
TALLOC_FREE(tmp_ctx);
SAFE_FREE(password);
return status;
return ADS_SUCCESS;
}
/* Query display info for a realm. This is the basic user list fn */