summaryrefslogtreecommitdiff
path: root/source4
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 /source4
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
Diffstat (limited to 'source4')
-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;