summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2009-06-18 12:33:46 +1000
committerAndrew Bartlett <abartlet@samba.org>2009-06-18 13:49:30 +1000
commit58e8db912d2213a594714ac29866396098662557 (patch)
tree1fba34e4ef93aa73e9839ad876460e6aa157a2fb
parent19413c52495877d54c90c60229568d0077fda30b (diff)
downloadsamba-58e8db912d2213a594714ac29866396098662557.tar.gz
s4:libnet Allow 'net password change' to work on expired passwords
We need to pass down flags to the DCE/RPC layer to allow fallback to anonymous connections, as we can't log in with an expired password. The anonymous connection can then change the password with SAMR. Andrew Bartlett
-rw-r--r--source4/libnet/libnet_domain.c4
-rw-r--r--source4/libnet/libnet_join.c2
-rw-r--r--source4/libnet/libnet_passwd.c6
-rw-r--r--source4/libnet/libnet_rpc.c19
-rw-r--r--source4/libnet/libnet_rpc.h1
-rw-r--r--source4/libnet/libnet_samsync.c2
-rw-r--r--source4/libnet/libnet_share.c6
-rw-r--r--source4/libnet/libnet_time.c2
-rw-r--r--source4/librpc/rpc/dcerpc.h2
-rw-r--r--source4/librpc/rpc/dcerpc_connect.c4
-rw-r--r--source4/torture/libnet/libnet_rpc.c2
11 files changed, 41 insertions, 9 deletions
diff --git a/source4/libnet/libnet_domain.c b/source4/libnet/libnet_domain.c
index eb6920d88ef..43a6a0e10b5 100644
--- a/source4/libnet/libnet_domain.c
+++ b/source4/libnet/libnet_domain.c
@@ -427,6 +427,8 @@ struct composite_context* libnet_DomainOpenLsa_send(struct libnet_context *ctx,
/* check, if there's lsa pipe opened already, before opening a handle */
if (ctx->lsa.pipe == NULL) {
+ ZERO_STRUCT(s->rpcconn);
+
/* attempting to connect a domain controller */
s->rpcconn.level = LIBNET_RPC_CONNECT_DC;
s->rpcconn.in.name = talloc_strdup(c, io->in.domain_name);
@@ -1179,6 +1181,8 @@ struct composite_context* libnet_DomainList_send(struct libnet_context *ctx,
/* check whether samr pipe has already been opened */
if (ctx->samr.pipe == NULL) {
+ ZERO_STRUCT(s->rpcconn);
+
/* prepare rpc connect call */
s->rpcconn.level = LIBNET_RPC_CONNECT_SERVER;
s->rpcconn.in.name = s->hostname;
diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c
index 0a4e357925a..81578a1a885 100644
--- a/source4/libnet/libnet_join.c
+++ b/source4/libnet/libnet_join.c
@@ -479,7 +479,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
return NT_STATUS_NO_MEMORY;
}
- connect_with_info = talloc(tmp_ctx, struct libnet_RpcConnect);
+ connect_with_info = talloc_zero(tmp_ctx, struct libnet_RpcConnect);
if (!connect_with_info) {
r->out.error_string = NULL;
talloc_free(tmp_ctx);
diff --git a/source4/libnet/libnet_passwd.c b/source4/libnet/libnet_passwd.c
index 2c969169373..e558c93d750 100644
--- a/source4/libnet/libnet_passwd.c
+++ b/source4/libnet/libnet_passwd.c
@@ -53,10 +53,13 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
struct samr_DomInfo1 *dominfo = NULL;
struct samr_ChangeReject *reject = NULL;
+ ZERO_STRUCT(c);
+
/* prepare connect to the SAMR pipe of the users domain PDC */
c.level = LIBNET_RPC_CONNECT_PDC;
c.in.name = r->samr.in.domain_name;
c.in.dcerpc_iface = &ndr_table_samr;
+ c.in.dcerpc_flags = DCERPC_ANON_FALLBACK;
/* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
status = libnet_RpcConnect(ctx, mem_ctx, &c);
@@ -504,11 +507,12 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX *
struct policy_handle u_handle;
union libnet_SetPassword r2;
+ ZERO_STRUCT(c);
/* prepare connect to the SAMR pipe of users domain PDC */
c.level = LIBNET_RPC_CONNECT_PDC;
c.in.name = r->samr.in.domain_name;
c.in.dcerpc_iface = &ndr_table_samr;
-
+
/* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
status = libnet_RpcConnect(ctx, mem_ctx, &c);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/libnet/libnet_rpc.c b/source4/libnet/libnet_rpc.c
index a0d93287a5b..66e12d0da14 100644
--- a/source4/libnet/libnet_rpc.c
+++ b/source4/libnet/libnet_rpc.c
@@ -106,6 +106,12 @@ static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context
return c;
}
+ switch (r->level) {
+ case LIBNET_RPC_CONNECT_SERVER:
+ case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
+ b->flags = r->in.dcerpc_flags;
+ }
+
if (r->level == LIBNET_RPC_CONNECT_SERVER_ADDRESS) {
b->target_hostname = talloc_reference(b, r->in.name);
if (composite_nomem(b->target_hostname, c)) {
@@ -323,6 +329,7 @@ static void continue_lookup_dc(struct composite_context *ctx)
s->r2.in.name = talloc_strdup(s, s->connect_name);
s->r2.in.address = talloc_steal(s, s->f.out.dcs[0].address);
s->r2.in.dcerpc_iface = s->r.in.dcerpc_iface;
+ s->r2.in.dcerpc_flags = s->r.in.dcerpc_flags;
/* send rpc connect request to the server */
rpc_connect_req = libnet_RpcConnectSrv_send(s->ctx, c, &s->r2, s->monitor_fn);
@@ -478,14 +485,18 @@ static struct composite_context* libnet_RpcConnectDCInfo_send(struct libnet_cont
s->r = *r;
ZERO_STRUCT(s->r.out);
+
/* proceed to pure rpc connection if the binding string is provided,
otherwise try to connect domain controller */
if (r->in.binding == NULL) {
- s->rpc_conn.in.name = r->in.name;
- s->rpc_conn.level = LIBNET_RPC_CONNECT_DC;
+ /* Pass on any binding flags (such as anonymous fallback) that have been set */
+ s->rpc_conn.in.dcerpc_flags = r->in.dcerpc_flags;
+
+ s->rpc_conn.in.name = r->in.name;
+ s->rpc_conn.level = LIBNET_RPC_CONNECT_DC;
} else {
- s->rpc_conn.in.binding = r->in.binding;
- s->rpc_conn.level = LIBNET_RPC_CONNECT_BINDING;
+ s->rpc_conn.in.binding = r->in.binding;
+ s->rpc_conn.level = LIBNET_RPC_CONNECT_BINDING;
}
/* we need to query information on lsarpc interface first */
diff --git a/source4/libnet/libnet_rpc.h b/source4/libnet/libnet_rpc.h
index b3e1620c75b..fb2628409f5 100644
--- a/source4/libnet/libnet_rpc.h
+++ b/source4/libnet/libnet_rpc.h
@@ -45,6 +45,7 @@ struct libnet_RpcConnect {
const char *address;
const char *binding;
const struct ndr_interface_table *dcerpc_iface;
+ int dcerpc_flags;
} in;
struct {
struct dcerpc_pipe *dcerpc_pipe;
diff --git a/source4/libnet/libnet_samsync.c b/source4/libnet/libnet_samsync.c
index 4d512d60344..1d5e41de053 100644
--- a/source4/libnet/libnet_samsync.c
+++ b/source4/libnet/libnet_samsync.c
@@ -77,7 +77,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
- c = talloc(samsync_ctx, struct libnet_RpcConnect);
+ c = talloc_zero(samsync_ctx, struct libnet_RpcConnect);
if (!c) {
r->out.error_string = NULL;
talloc_free(samsync_ctx);
diff --git a/source4/libnet/libnet_share.c b/source4/libnet/libnet_share.c
index 0bf6749a9c1..e9ad83db36a 100644
--- a/source4/libnet/libnet_share.c
+++ b/source4/libnet/libnet_share.c
@@ -37,6 +37,8 @@ NTSTATUS libnet_ListShares(struct libnet_context *ctx,
struct srvsvc_NetShareCtr501 ctr501;
struct srvsvc_NetShareCtr502 ctr502;
+ ZERO_STRUCT(c);
+
c.level = LIBNET_RPC_CONNECT_SERVER;
c.in.name = r->in.server_name;
c.in.dcerpc_iface = &ndr_table_srvsvc;
@@ -121,6 +123,8 @@ NTSTATUS libnet_AddShare(struct libnet_context *ctx,
struct srvsvc_NetShareAdd s;
union srvsvc_NetShareInfo info;
+ ZERO_STRUCT(c);
+
c.level = LIBNET_RPC_CONNECT_SERVER;
c.in.name = r->in.server_name;
c.in.dcerpc_iface = &ndr_table_srvsvc;
@@ -170,6 +174,8 @@ NTSTATUS libnet_DelShare(struct libnet_context *ctx,
struct libnet_RpcConnect c;
struct srvsvc_NetShareDel s;
+ ZERO_STRUCT(c);
+
c.level = LIBNET_RPC_CONNECT_SERVER;
c.in.name = r->in.server_name;
c.in.dcerpc_iface = &ndr_table_srvsvc;
diff --git a/source4/libnet/libnet_time.c b/source4/libnet/libnet_time.c
index 61a451d3fda..37648459db9 100644
--- a/source4/libnet/libnet_time.c
+++ b/source4/libnet/libnet_time.c
@@ -33,6 +33,8 @@ static NTSTATUS libnet_RemoteTOD_srvsvc(struct libnet_context *ctx, TALLOC_CTX *
struct srvsvc_NetRemoteTODInfo *info = NULL;
struct tm tm;
+ ZERO_STRUCT(c);
+
/* prepare connect to the SRVSVC pipe of a timeserver */
c.level = LIBNET_RPC_CONNECT_SERVER;
c.in.name = r->srvsvc.in.server_name;
diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h
index 7f573f0e84f..ea92bcc93a4 100644
--- a/source4/librpc/rpc/dcerpc.h
+++ b/source4/librpc/rpc/dcerpc.h
@@ -142,6 +142,8 @@ struct dcerpc_pipe {
#define DCERPC_SCHANNEL (1<<9)
+#define DCERPC_ANON_FALLBACK (1<<10)
+
/* use a 128 bit session key */
#define DCERPC_SCHANNEL_128 (1<<12)
diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c
index 0f9fbe0abc0..1b1f039004f 100644
--- a/source4/librpc/rpc/dcerpc_connect.c
+++ b/source4/librpc/rpc/dcerpc_connect.c
@@ -130,10 +130,10 @@ static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CT
* provide proper credentials - user supplied, but allow a
* fallback to anonymous if this is an schannel connection
* (might be NT4 not allowing machine logins at session
- * setup).
+ * setup) or if asked to do so by the caller (perhaps a SAMR password change?)
*/
s->conn.in.credentials = s->io.creds;
- if (s->io.binding->flags & DCERPC_SCHANNEL) {
+ if (s->io.binding->flags & (DCERPC_SCHANNEL|DCERPC_ANON_FALLBACK)) {
conn->in.fallback_to_anonymous = true;
} else {
conn->in.fallback_to_anonymous = false;
diff --git a/source4/torture/libnet/libnet_rpc.c b/source4/torture/libnet/libnet_rpc.c
index 0bcfcb6a4cd..c9ba8755895 100644
--- a/source4/torture/libnet/libnet_rpc.c
+++ b/source4/torture/libnet/libnet_rpc.c
@@ -42,6 +42,8 @@ static bool test_connect_service(struct libnet_context *ctx,
{
NTSTATUS status;
struct libnet_RpcConnect connect_r;
+ ZERO_STRUCT(connect_r);
+
connect_r.level = level;
connect_r.in.binding = binding_string;
connect_r.in.name = hostname;