#include "winbindd.h"
#include "../libcli/auth/libcli_auth.h"
#include "../librpc/gen_ndr/cli_netlogon.h"
+#include "rpc_client/cli_netlogon.h"
#include "../librpc/gen_ndr/cli_samr.h"
#include "../librpc/gen_ndr/cli_lsa.h"
+#include "rpc_client/cli_lsarpc.h"
#include "../librpc/gen_ndr/cli_dssetup.h"
+#include "libads/sitename_cache.h"
+#include "librpc/gen_ndr/messaging.h"
+#include "libsmb/clidgram.h"
+#include "ads.h"
+#include "secrets.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
pid_t parent_pid = sys_getpid();
char *lfile = NULL;
- /* Stop zombies */
- CatchChild();
-
if (domain->dc_probe_pid != (pid_t)-1) {
/*
* We might already have a DC probe
peeraddr_len = sizeof(peeraddr);
- if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
- (peeraddr_len != sizeof(struct sockaddr_in)) ||
- (peeraddr_in->sin_family != PF_INET))
- {
- DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
+ if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0)) {
+ DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
+ strerror(errno)));
+ result = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if ((peeraddr_len != sizeof(struct sockaddr_in))
+#ifdef HAVE_IPV6
+ && (peeraddr_len != sizeof(struct sockaddr_in6))
+#endif
+ ) {
+ DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
+ peeraddr_len));
+ result = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if ((peeraddr_in->sin_family != PF_INET)
+#ifdef HAVE_IPV6
+ && (peeraddr_in->sin_family != PF_INET6)
+#endif
+ ) {
+ DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
+ peeraddr_in->sin_family));
result = NT_STATUS_UNSUCCESSFUL;
goto done;
}
create_local_private_krb5_conf_for_domain(domain->alt_name,
domain->name,
sitename,
- pss);
+ pss,
+ name);
SAFE_FREE(sitename);
} else {
create_local_private_krb5_conf_for_domain(domain->alt_name,
domain->name,
NULL,
- pss);
+ pss,
+ name);
}
winbindd_set_locator_kdc_envs(domain);
}
if (conn->samr_pipe != NULL) {
+ if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
+ rpccli_samr_Close(conn->samr_pipe, talloc_tos(),
+ &conn->sam_connect_handle);
+ }
TALLOC_FREE(conn->samr_pipe);
/* Ok, it must be dead. Drop timeout to 0.5 sec. */
if (conn->cli) {
}
if (conn->lsa_pipe != NULL) {
+ if (is_valid_policy_hnd(&conn->lsa_policy)) {
+ rpccli_lsa_Close(conn->lsa_pipe, talloc_tos(),
+ &conn->lsa_policy);
+ }
TALLOC_FREE(conn->lsa_pipe);
/* Ok, it must be dead. Drop timeout to 0.5 sec. */
if (conn->cli) {
}
if (conn->lsa_pipe_tcp != NULL) {
+ if (is_valid_policy_hnd(&conn->lsa_policy)) {
+ rpccli_lsa_Close(conn->lsa_pipe, talloc_tos(),
+ &conn->lsa_policy);
+ }
TALLOC_FREE(conn->lsa_pipe_tcp);
/* Ok, it must be dead. Drop timeout to 0.5 sec. */
if (conn->cli) {
struct winbindd_domain *domain;
for (domain = domain_list(); domain; domain = domain->next) {
- if (domain->conn.cli == NULL)
- continue;
+ struct cli_state *cli = domain->conn.cli;
- if (domain->conn.cli->fd == -1)
- continue;
+ /*
+ * first close the low level SMB TCP connection
+ * so that we don't generate any SMBclose
+ * requests in invalidate_cm_connection()
+ */
+ if (cli && cli->fd != -1) {
+ close(domain->conn.cli->fd);
+ domain->conn.cli->fd = -1;
+ }
- close(domain->conn.cli->fd);
- domain->conn.cli->fd = -1;
+ invalidate_cm_connection(&domain->conn);
}
}
static bool connection_ok(struct winbindd_domain *domain)
{
- if (domain->conn.cli == NULL) {
- DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
- "cli!\n", domain->dcname, domain->name));
- return False;
- }
-
- if (!domain->conn.cli->initialised) {
- DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
- "initialised!\n", domain->dcname, domain->name));
- return False;
- }
+ bool ok;
- if (domain->conn.cli->fd == -1) {
- DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
- "never started (fd == -1)\n",
+ ok = cli_state_is_connected(domain->conn.cli);
+ if (!ok) {
+ DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
domain->dcname, domain->name));
return False;
}
NTSTATUS result;
/* Internal connections never use the network. */
- if (domain->internal || !winbindd_can_contact_domain(domain)) {
+ if (domain->internal) {
+ domain->initialized = True;
+ return NT_STATUS_OK;
+ }
+
+ if (!winbindd_can_contact_domain(domain)) {
+ invalidate_cm_connection(&domain->conn);
domain->initialized = True;
return NT_STATUS_OK;
}
NTSTATUS init_dc_connection(struct winbindd_domain *domain)
{
+ if (domain->internal) {
+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ }
+
if (domain->initialized && !domain->online) {
/* We check for online status elsewhere. */
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
return init_dc_connection_network(domain);
}
+static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
+{
+ NTSTATUS status;
+
+ status = init_dc_connection(domain);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (!domain->internal && domain->conn.cli == NULL) {
+ /* happens for trusted domains without inbound trust */
+ return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
+ }
+
+ return NT_STATUS_OK;
+}
+
/******************************************************************************
Set the trust flags (direction and forest location) for a domain
******************************************************************************/
char *machine_account = NULL;
char *domain_name = NULL;
- result = init_dc_connection(domain);
+ if (strequal(domain->name, get_global_sam_name())) {
+ result = open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+ return NT_STATUS_OK;
+ }
+
+ result = init_dc_connection_rpc(domain);
if (!NT_STATUS_IS_OK(result)) {
return result;
}
conn = &domain->conn;
- if (conn->samr_pipe != NULL) {
+ if (rpccli_is_connected(conn->samr_pipe)) {
goto done;
}
+ TALLOC_FREE(conn->samr_pipe);
/*
* No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
struct rpc_pipe_client **cli)
{
struct winbindd_cm_conn *conn;
+ struct netlogon_creds_CredentialState *creds;
NTSTATUS status;
DEBUG(10,("cm_connect_lsa_tcp\n"));
- status = init_dc_connection(domain);
+ status = init_dc_connection_rpc(domain);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
if (conn->lsa_pipe_tcp &&
conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
- rpc_pipe_tcp_connection_ok(conn->lsa_pipe_tcp)) {
+ rpccli_is_connected(conn->lsa_pipe_tcp)) {
goto done;
}
TALLOC_FREE(conn->lsa_pipe_tcp);
- status = cli_rpc_pipe_open_schannel(conn->cli,
- &ndr_table_lsarpc.syntax_id,
- NCACN_IP_TCP,
- DCERPC_AUTH_LEVEL_PRIVACY,
- domain->name,
- &conn->lsa_pipe_tcp);
+ if (!cm_get_schannel_creds(domain, &creds)) {
+ goto done;
+ }
+
+ status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
+ &ndr_table_lsarpc.syntax_id,
+ NCACN_IP_TCP,
+ DCERPC_AUTH_LEVEL_PRIVACY,
+ domain->name,
+ &creds,
+ &conn->lsa_pipe_tcp);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10,("cli_rpc_pipe_open_schannel failed: %s\n",
+ DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
nt_errstr(status)));
goto done;
}
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
struct netlogon_creds_CredentialState *p_creds;
- result = init_dc_connection(domain);
+ result = init_dc_connection_rpc(domain);
if (!NT_STATUS_IS_OK(result))
return result;
conn = &domain->conn;
- if (conn->lsa_pipe != NULL) {
+ if (rpccli_is_connected(conn->lsa_pipe)) {
goto done;
}
+ TALLOC_FREE(conn->lsa_pipe);
+
if ((conn->cli->user_name[0] == '\0') ||
(conn->cli->domain[0] == '\0') ||
(conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
*cli = NULL;
- result = init_dc_connection(domain);
+ result = init_dc_connection_rpc(domain);
if (!NT_STATUS_IS_OK(result)) {
return result;
}
conn = &domain->conn;
- if (conn->netlogon_pipe != NULL) {
+ if (rpccli_is_connected(conn->netlogon_pipe)) {
*cli = conn->netlogon_pipe;
return NT_STATUS_OK;
}
+ TALLOC_FREE(conn->netlogon_pipe);
+
result = cli_rpc_pipe_open_noauth(conn->cli,
&ndr_table_netlogon.syntax_id,
&netlogon_pipe);
DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
"was %s\n", nt_errstr(result)));
- /* make sure we return something besides OK */
- return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
+ invalidate_cm_connection(conn);
+ return result;
}
/*