summaryrefslogtreecommitdiff
path: root/source3/winbindd/winbindd_cm.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/winbindd/winbindd_cm.c')
-rw-r--r--source3/winbindd/winbindd_cm.c205
1 files changed, 140 insertions, 65 deletions
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index cb366a293c..d2a7663002 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -74,7 +74,7 @@ extern bool override_logfile;
static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
static void set_dc_type_and_flags( struct winbindd_domain *domain );
-static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
+static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
struct dc_name_ip **dcs, int *num_dcs);
/****************************************************************
@@ -560,7 +560,7 @@ static void cm_get_ipc_userpass(char **username, char **domain, char **password)
}
}
-static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain,
+static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
fstring dcname,
struct sockaddr_storage *dc_ss)
{
@@ -570,7 +570,7 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain,
WERROR werr;
TALLOC_CTX *mem_ctx;
unsigned int orig_timeout;
- fstring tmp;
+ char *tmp = NULL;
char *p;
/* Hmmmm. We can only open one connection to the NETLOGON pipe at the
@@ -600,18 +600,51 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain,
35 seconds should do it. */
orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
-
- werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
- domain->name, tmp);
+
+ if (our_domain->active_directory) {
+ struct DS_DOMAIN_CONTROLLER_INFO *domain_info = NULL;
+
+ werr = rpccli_netlogon_dsr_getdcname(netlogon_pipe,
+ mem_ctx,
+ our_domain->dcname,
+ domain->name,
+ NULL,
+ NULL,
+ DS_RETURN_DNS_NAME,
+ &domain_info);
+ if (W_ERROR_IS_OK(werr)) {
+ tmp = talloc_strdup(
+ mem_ctx, domain_info->domain_controller_name);
+ if (tmp == NULL) {
+ DEBUG(0, ("talloc_strdup failed\n"));
+ talloc_destroy(mem_ctx);
+ return false;
+ }
+ if (strlen(domain->alt_name) == 0) {
+ fstrcpy(domain->alt_name,
+ domain_info->domain_name);
+ }
+ if (strlen(domain->forest_name) == 0) {
+ fstrcpy(domain->forest_name,
+ domain_info->dns_forest_name);
+ }
+ }
+ } else {
+
+ werr = rpccli_netlogon_getanydcname(netlogon_pipe,
+ mem_ctx,
+ our_domain->dcname,
+ domain->name,
+ &tmp);
+ }
/* And restore our original timeout. */
cli_set_timeout(netlogon_pipe->cli, orig_timeout);
- talloc_destroy(mem_ctx);
-
if (!W_ERROR_IS_OK(werr)) {
DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
dos_errstr(werr)));
+ talloc_destroy(mem_ctx);
return False;
}
@@ -626,6 +659,8 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain,
fstrcpy(dcname, p);
+ talloc_destroy(mem_ctx);
+
DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
if (!resolve_name(dcname, dc_ss, 0x20)) {
@@ -644,8 +679,22 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
char **machine_krb5_principal)
{
const char *account_name;
+ const char *name = NULL;
+
+ /* If we are a DC and this is not our own domain */
- if (!get_trust_pw_clear(domain->name, machine_password,
+ if (IS_DC) {
+ name = domain->name;
+ } else {
+ struct winbindd_domain *our_domain = find_our_domain();
+
+ if (!our_domain)
+ return NT_STATUS_INVALID_SERVER_STATE;
+
+ name = our_domain->name;
+ }
+
+ if (!get_trust_pw_clear(name, machine_password,
&account_name, NULL))
{
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
@@ -659,11 +708,15 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
/* this is at least correct when domain is our domain,
* which is the only case, when this is currently used: */
- if ((machine_krb5_principal != NULL) &&
- (asprintf(machine_krb5_principal, "%s$@%s", account_name,
- domain->alt_name) == -1))
+ if (machine_krb5_principal != NULL)
{
- return NT_STATUS_NO_MEMORY;
+ if (asprintf(machine_krb5_principal, "%s$@%s",
+ account_name, domain->alt_name) == -1)
+ {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ strupper_m(*machine_krb5_principal);
}
return NT_STATUS_OK;
@@ -978,6 +1031,7 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss,
char *p;
fstring my_acct_name;
fstring my_mailslot;
+ size_t sid_size;
if (dc_ss->ss_family != AF_INET) {
return false;
@@ -1019,7 +1073,9 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss,
SIVAL(p, 0, 0x80);
p+=4;
- SIVAL(p, 0, sid_size(sid));
+ sid_size = ndr_size_dom_sid(sid, 0);
+
+ SIVAL(p, 0, sid_size);
p+=4;
p = ALIGN4(p, outbuf);
@@ -1027,12 +1083,12 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss,
return false;
}
- sid_linearize(p, sid_size(sid), sid);
- if (sid_size(sid) + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
+ if (sid_size + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
return false;
}
+ sid_linearize(p, sizeof(outbuf) - PTR_DIFF(p, outbuf), sid);
- p += sid_size(sid);
+ p += sid_size;
SIVAL(p, 0, 1);
SSVAL(p, 4, 0xffff);
@@ -1216,7 +1272,7 @@ static bool dcip_to_name(const struct winbindd_domain *domain,
the dcs[] with results.
*******************************************************************/
-static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
+static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
struct dc_name_ip **dcs, int *num_dcs)
{
fstring dcname;
@@ -1319,7 +1375,7 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
}
static bool find_new_dc(TALLOC_CTX *mem_ctx,
- const struct winbindd_domain *domain,
+ struct winbindd_domain *domain,
fstring dcname, struct sockaddr_storage *pss, int *fd)
{
struct dc_name_ip *dcs = NULL;
@@ -1660,12 +1716,11 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
{
struct winbindd_domain *our_domain;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- struct ds_domain_trust *domains = NULL;
- int count = 0;
+ struct netr_DomainTrustList trusts;
int i;
- uint32 flags = (DS_DOMAIN_IN_FOREST |
- DS_DOMAIN_DIRECT_OUTBOUND |
- DS_DOMAIN_DIRECT_INBOUND);
+ uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
+ NETR_TRUST_FLAG_OUTBOUND |
+ NETR_TRUST_FLAG_INBOUND);
struct rpc_pipe_client *cli;
TALLOC_CTX *mem_ctx = NULL;
@@ -1707,27 +1762,35 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
return False;
}
- result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
- cli->cli->desthost,
- flags, &domains,
- (unsigned int *)&count);
+ result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
+ cli->cli->desthost,
+ flags,
+ &trusts,
+ NULL);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(0,("set_dc_type_and_flags_trustinfo: "
+ "failed to query trusted domain list: %s\n",
+ nt_errstr(result)));
+ talloc_destroy(mem_ctx);
+ return false;
+ }
/* Now find the domain name and get the flags */
- for ( i=0; i<count; i++ ) {
- if ( strequal( domain->name, domains[i].netbios_domain ) ) {
- domain->domain_flags = domains[i].flags;
- domain->domain_type = domains[i].trust_type;
- domain->domain_trust_attribs = domains[i].trust_attributes;
-
- if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
+ for ( i=0; i<trusts.count; i++ ) {
+ if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
+ domain->domain_flags = trusts.array[i].trust_flags;
+ domain->domain_type = trusts.array[i].trust_type;
+ domain->domain_trust_attribs = trusts.array[i].trust_attributes;
+
+ if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
domain->active_directory = True;
/* This flag is only set if the domain is *our*
primary domain and the primary domain is in
native mode */
- domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
+ domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
"native mode.\n", domain->name,
@@ -1763,17 +1826,17 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
{
NTSTATUS result;
- DS_DOMINFO_CTR ctr;
+ WERROR werr;
TALLOC_CTX *mem_ctx = NULL;
struct rpc_pipe_client *cli;
POLICY_HND pol;
+ union dssetup_DsRoleInfo info;
- char *domain_name = NULL;
- char *dns_name = NULL;
- char *forest_name = NULL;
+ const char *domain_name = NULL;
+ const char *dns_name = NULL;
+ const char *forest_name = NULL;
DOM_SID *dom_sid = NULL;
- ZERO_STRUCT( ctr );
if (!connection_ok(domain)) {
return;
@@ -1788,24 +1851,25 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
- cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
+ cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_DSSETUP,
&result);
if (cli == NULL) {
DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
- "PI_LSARPC_DS on domain %s: (%s)\n",
+ "PI_DSSETUP on domain %s: (%s)\n",
domain->name, nt_errstr(result)));
/* if this is just a non-AD domain we need to continue
* identifying so that we can in the end return with
* domain->initialized = True - gd */
- goto no_lsarpc_ds;
+ goto no_dssetup;
}
- result = rpccli_ds_getprimarydominfo(cli, mem_ctx,
- DsRolePrimaryDomainInfoBasic,
- &ctr);
+ result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
+ DS_ROLE_BASIC_INFORMATION,
+ &info,
+ &werr);
cli_rpc_pipe_close(cli);
if (!NT_STATUS_IS_OK(result)) {
@@ -1814,26 +1878,26 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
domain->name, nt_errstr(result)));
/* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
- * every opcode on the LSARPC_DS pipe, continue with
- * no_lsarpc_ds mode here as well to get domain->initialized
+ * every opcode on the DSSETUP pipe, continue with
+ * no_dssetup mode here as well to get domain->initialized
* set - gd */
if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
- goto no_lsarpc_ds;
+ goto no_dssetup;
}
TALLOC_FREE(mem_ctx);
return;
}
-
- if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
- !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
+
+ if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
+ !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
domain->native_mode = True;
} else {
domain->native_mode = False;
}
-no_lsarpc_ds:
+no_dssetup:
cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
if (cli == NULL) {
@@ -1866,9 +1930,17 @@ no_lsarpc_ds:
if (dns_name)
fstrcpy(domain->alt_name, dns_name);
- if ( forest_name )
+ /* See if we can set some domain trust flags about
+ ourself */
+
+ if ( forest_name ) {
fstrcpy(domain->forest_name, forest_name);
+ if (strequal(domain->forest_name, domain->alt_name)) {
+ domain->domain_flags = NETR_TRUST_FLAG_TREEROOT;
+ }
+ }
+
if (dom_sid)
sid_copy(&domain->sid, dom_sid);
} else {
@@ -2003,13 +2075,16 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
goto schannel;
}
domain_name = domain->name;
- goto schannel;
} else {
- machine_password = conn_pwd;
- machine_account = conn->cli->user_name;
+ machine_password = SMB_STRDUP(conn_pwd);
+ machine_account = SMB_STRDUP(conn->cli->user_name);
domain_name = conn->cli->domain;
}
+ if (!machine_password || !machine_account) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
/* We have an authenticated connection. Use a NTLMSSP SPNEGO
authenticated SAMR pipe with sign & seal. */
@@ -2101,12 +2176,12 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
}
open_domain:
- result = rpccli_samr_open_domain(conn->samr_pipe,
- mem_ctx,
- &conn->sam_connect_handle,
- SEC_RIGHTS_MAXIMUM_ALLOWED,
- &domain->sid,
- &conn->sam_domain_handle);
+ result = rpccli_samr_OpenDomain(conn->samr_pipe,
+ mem_ctx,
+ &conn->sam_connect_handle,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &domain->sid,
+ &conn->sam_domain_handle);
done:
@@ -2249,7 +2324,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
struct winbindd_cm_conn *conn;
NTSTATUS result;
- uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+ uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS;
uint8 mach_pwd[16];
uint32 sec_chan_type;
const char *account_name;