summaryrefslogtreecommitdiff
path: root/source4/libnet
diff options
context:
space:
mode:
Diffstat (limited to 'source4/libnet')
-rw-r--r--source4/libnet/config.mk2
-rw-r--r--source4/libnet/libnet_join.c22
-rw-r--r--source4/libnet/libnet_lookup.c48
-rw-r--r--source4/libnet/libnet_lookup.h12
-rw-r--r--source4/libnet/libnet_passwd.c8
-rw-r--r--source4/libnet/libnet_rpc.c45
-rw-r--r--source4/libnet/libnet_rpc.h4
-rw-r--r--source4/libnet/libnet_share.c56
-rw-r--r--source4/libnet/libnet_time.c8
-rw-r--r--source4/libnet/libnet_user.c18
-rw-r--r--source4/libnet/libnet_vampire.c2
11 files changed, 160 insertions, 65 deletions
diff --git a/source4/libnet/config.mk b/source4/libnet/config.mk
index b76fe0c7e5..baf81e36e6 100644
--- a/source4/libnet/config.mk
+++ b/source4/libnet/config.mk
@@ -25,6 +25,6 @@ OBJ_FILES = \
userinfo.o \
userman.o \
domain.o
-REQUIRED_SUBSYSTEMS = RPC_NDR_SAMR RPC_NDR_LSA RPC_NDR_SRVSVC RPC_NDR_DRSUAPI LIBCLI_COMPOSITE LIBCLI_RESOLVE LIBSAMBA3 LIBCLI_CLDAP gensec_schannel
+REQUIRED_SUBSYSTEMS = RPC_NDR_SAMR RPC_NDR_LSA RPC_NDR_SRVSVC RPC_NDR_DRSUAPI LIBCLI_COMPOSITE LIBCLI_RESOLVE LIBCLI_FINDDCS LIBSAMBA3 LIBCLI_CLDAP LIBCLI_FINDDCS gensec_schannel
# End SUBSYSTEM LIBNET
#################################
diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c
index 4f566a36a8..616c80b1a4 100644
--- a/source4/libnet/libnet_join.c
+++ b/source4/libnet/libnet_join.c
@@ -272,7 +272,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
status = dcerpc_pipe_connect_b(tmp_ctx,
&drsuapi_pipe,
drsuapi_binding,
- &dcerpc_table_drsuapi,
+ &dcerpc_table_drsuapi,
ctx->cred,
ctx->event_ctx);
if (!NT_STATUS_IS_OK(status)) {
@@ -635,8 +635,8 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
/* prepare connect to the LSA pipe of PDC */
if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) {
- c->level = LIBNET_RPC_CONNECT_PDC;
- c->in.domain_name = r->in.domain_name;
+ c->level = LIBNET_RPC_CONNECT_PDC;
+ c->in.name = r->in.domain_name;
} else {
c->level = LIBNET_RPC_CONNECT_BINDING;
c->in.binding = r->in.binding;
@@ -998,7 +998,9 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
/* We created a new user, but they didn't come out the right type?!? */
r->out.error_string
= talloc_asprintf(mem_ctx,
- "We asked to create a new machine account (%s) of type %s, but we got an account of type %s. This is unexpected. Perhaps delete the account and try again.\n",
+ "We asked to create a new machine account (%s) of type %s, "
+ "but we got an account of type %s. This is unexpected. "
+ "Perhaps delete the account and try again.\n",
r->in.account_name, new_account_type, old_account_type);
talloc_free(tmp_ctx);
return NT_STATUS_INVALID_PARAMETER;
@@ -1008,7 +1010,9 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
/* TODO: We should allow a --force option to override, and redo this from the top setting r.in.recreate_account */
r->out.error_string
= talloc_asprintf(mem_ctx,
- "The machine account (%s) already exists in the domain %s, but is a %s. You asked to join as a %s. Please delete the account and try again.\n",
+ "The machine account (%s) already exists in the domain %s, "
+ "but is a %s. You asked to join as a %s. Please delete "
+ "the account and try again.\n",
r->in.account_name, domain_name, old_account_type, new_account_type);
talloc_free(tmp_ctx);
return NT_STATUS_USER_EXISTS;
@@ -1045,7 +1049,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
}
/* reset flags (if required) */
- if (acct_flags != qui.out.info->info16.acct_flags) {
+ if (acct_flags != qui.out.info->info16.acct_flags) {
ZERO_STRUCT(u_info);
u_info.info16.acct_flags = acct_flags;
@@ -1160,7 +1164,7 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
if ((r->in.netbios_name != NULL) && (r->in.level != LIBNET_JOIN_AUTOMATIC)) {
netbios_name = r->in.netbios_name;
} else {
- netbios_name = talloc_asprintf(tmp_mem, "%s", lp_netbios_name());
+ netbios_name = talloc_reference(tmp_mem, lp_netbios_name());
if (!netbios_name) {
r->out.error_string = NULL;
talloc_free(tmp_mem);
@@ -1437,8 +1441,8 @@ NTSTATUS libnet_Join(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct lib
}
r->out.error_string = talloc_asprintf(mem_ctx,
- "Invalid secure channel type specified (%08X) attempting to join domain %s",
- r->in.secure_channel_type, r->in.domain_name);
+ "Invalid secure channel type specified (%08X) attempting to join domain %s",
+ r->in.secure_channel_type, r->in.domain_name);
return NT_STATUS_INVALID_PARAMETER;
}
diff --git a/source4/libnet/libnet_lookup.c b/source4/libnet/libnet_lookup.c
index e64ab6a291..1c1604f407 100644
--- a/source4/libnet/libnet_lookup.c
+++ b/source4/libnet/libnet_lookup.c
@@ -26,7 +26,8 @@
#include "lib/events/events.h"
#include "libnet/libnet.h"
#include "libcli/composite/composite.h"
-
+#include "lib/messaging/messaging.h"
+#include "lib/messaging/irpc.h"
struct lookup_state {
struct composite_context *resolve_ctx;
@@ -162,20 +163,49 @@ NTSTATUS libnet_LookupHost(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
/**
* Sends asynchronous LookupPdc request
*/
-struct composite_context* libnet_LookupPdc_send(struct libnet_context *ctx,
- struct libnet_Lookup *io)
+struct composite_context* libnet_LookupDCs_send(struct libnet_context *ctx,
+ TALLOC_CTX *mem_ctx,
+ struct libnet_LookupDCs *io)
{
- io->in.type = NBT_NAME_PDC;
- return libnet_Lookup_send(ctx, io);
+ struct messaging_context *msg_ctx = messaging_init(mem_ctx, random() % 0x10000000, ctx->event_ctx);
+ struct composite_context *c;
+ if (!msg_ctx) {
+ return NULL;
+ }
+ c = finddcs_send(mem_ctx,
+ io->in.domain_name,
+ NBT_NAME_PDC,
+ NULL, ctx->name_res_methods,
+ ctx->event_ctx, msg_ctx);
+ return c;
}
+/**
+ * Waits for and receives results of asynchronous Lookup call
+ *
+ * @param c composite context returned by asynchronous Lookup call
+ * @param mem_ctx memory context of the call
+ * @param io pointer to results (and arguments) of the call
+ * @return nt status code of execution
+ */
+
+NTSTATUS libnet_LookupDCs_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
+ struct libnet_LookupDCs *io)
+{
+ NTSTATUS status;
+ status = finddcs_recv(c, mem_ctx, &io->out.num_dcs, &io->out.dcs);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ return status;
+}
/**
* Synchronous version of LookupPdc
*/
-NTSTATUS libnet_LookupPdc(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
- struct libnet_Lookup *io)
+NTSTATUS libnet_LookupDCs(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
+ struct libnet_LookupDCs *io)
{
- struct composite_context *c = libnet_LookupPdc_send(ctx, io);
- return libnet_Lookup_recv(c, mem_ctx, io);
+ struct composite_context *c = libnet_LookupDCs_send(ctx, mem_ctx, io);
+ return libnet_LookupDCs_recv(c, mem_ctx, io);
}
diff --git a/source4/libnet/libnet_lookup.h b/source4/libnet/libnet_lookup.h
index e5b2d58fd3..c786eb0a43 100644
--- a/source4/libnet/libnet_lookup.h
+++ b/source4/libnet/libnet_lookup.h
@@ -29,3 +29,15 @@ struct libnet_Lookup {
const char **address;
} out;
};
+
+struct libnet_LookupDCs {
+ struct {
+ const char *domain_name;
+ int name_type;
+ } in;
+ struct {
+ int num_dcs;
+ struct nbt_dc_name *dcs;
+ } out;
+};
+
diff --git a/source4/libnet/libnet_passwd.c b/source4/libnet/libnet_passwd.c
index bd09e306ce..fe5239f4b6 100644
--- a/source4/libnet/libnet_passwd.c
+++ b/source4/libnet/libnet_passwd.c
@@ -53,7 +53,7 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT
/* prepare connect to the SAMR pipe of the users domain PDC */
c.level = LIBNET_RPC_CONNECT_PDC;
- c.in.domain_name = r->samr.in.domain_name;
+ c.in.name = r->samr.in.domain_name;
c.in.dcerpc_iface = &dcerpc_table_samr;
/* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
@@ -513,9 +513,9 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX *
union libnet_SetPassword r2;
/* prepare connect to the SAMR pipe of users domain PDC */
- c.level = LIBNET_RPC_CONNECT_PDC;
- c.in.domain_name = r->samr.in.domain_name;
- c.in.dcerpc_iface = &dcerpc_table_samr;
+ c.level = LIBNET_RPC_CONNECT_PDC;
+ c.in.name = r->samr.in.domain_name;
+ c.in.dcerpc_iface = &dcerpc_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);
diff --git a/source4/libnet/libnet_rpc.c b/source4/libnet/libnet_rpc.c
index 6b94734f9b..ffed674f1f 100644
--- a/source4/libnet/libnet_rpc.c
+++ b/source4/libnet/libnet_rpc.c
@@ -21,7 +21,7 @@
#include "includes.h"
#include "libnet/libnet.h"
-
+#include "libcli/libcli.h"
/**
* Connects rpc pipe on remote server
@@ -39,9 +39,10 @@ static NTSTATUS libnet_RpcConnectSrv(struct libnet_context *ctx, TALLOC_CTX *mem
/* prepare binding string */
switch (r->level) {
+ case LIBNET_RPC_CONNECT_DC:
case LIBNET_RPC_CONNECT_PDC:
case LIBNET_RPC_CONNECT_SERVER:
- binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", r->in.domain_name);
+ binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", r->in.name);
break;
case LIBNET_RPC_CONNECT_BINDING:
@@ -81,24 +82,45 @@ static NTSTATUS libnet_RpcConnectPdc(struct libnet_context *ctx, TALLOC_CTX *mem
{
NTSTATUS status;
struct libnet_RpcConnect r2;
- struct libnet_Lookup f;
+ struct libnet_LookupDCs f;
+ const char *connect_name;
- f.in.hostname = r->in.domain_name;
- f.in.methods = NULL;
- f.out.address = NULL;
+ f.in.domain_name = r->in.name;
+ switch (r->level) {
+ case LIBNET_RPC_CONNECT_PDC:
+ f.in.name_type = NBT_NAME_PDC;
+ break;
+ case LIBNET_RPC_CONNECT_DC:
+ f.in.name_type = NBT_NAME_LOGON;
+ break;
+ default:
+ break;
+ }
+ f.out.num_dcs = 0;
+ f.out.dcs = NULL;
/* find the domain pdc first */
- status = libnet_LookupPdc(ctx, mem_ctx, &f);
+ status = libnet_LookupDCs(ctx, mem_ctx, &f);
if (!NT_STATUS_IS_OK(status)) {
- r->out.error_string = talloc_asprintf(mem_ctx, "libnet_LookupPdc failed: %s",
+ r->out.error_string = talloc_asprintf(mem_ctx, "libnet_LookupDCs failed: %s",
nt_errstr(status));
return status;
}
+ /* we might not have got back a name. Fall back to the IP */
+ if (f.out.dcs[0].name) {
+ connect_name = f.out.dcs[0].name;
+ } else {
+ connect_name = f.out.dcs[0].address;
+ }
+
/* ok, pdc has been found so do attempt to rpc connect */
- r2.level = LIBNET_RPC_CONNECT_SERVER;
- r2.in.domain_name = talloc_strdup(mem_ctx, f.out.address[0]);
- r2.in.dcerpc_iface = r->in.dcerpc_iface;
+ r2.level = LIBNET_RPC_CONNECT_SERVER;
+
+ /* This will cause yet another name resolution, but at least
+ * we pass the right name down the stack now */
+ r2.in.name = talloc_strdup(mem_ctx, connect_name);
+ r2.in.dcerpc_iface = r->in.dcerpc_iface;
status = libnet_RpcConnect(ctx, mem_ctx, &r2);
@@ -130,6 +152,7 @@ NTSTATUS libnet_RpcConnect(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
return libnet_RpcConnectSrv(ctx, mem_ctx, r);
case LIBNET_RPC_CONNECT_PDC:
+ case LIBNET_RPC_CONNECT_DC:
return libnet_RpcConnectPdc(ctx, mem_ctx, r);
}
diff --git a/source4/libnet/libnet_rpc.h b/source4/libnet/libnet_rpc.h
index d2a83bf642..5505e69a09 100644
--- a/source4/libnet/libnet_rpc.h
+++ b/source4/libnet/libnet_rpc.h
@@ -27,6 +27,8 @@ enum libnet_RpcConnect_level {
LIBNET_RPC_CONNECT_SERVER, /* connect to a standalone rpc server */
LIBNET_RPC_CONNECT_PDC, /* connect to a domain pdc (resolves domain
name to a pdc address before connecting) */
+ LIBNET_RPC_CONNECT_DC, /* connect to any DC (resolves domain
+ name to a DC address before connecting) */
LIBNET_RPC_CONNECT_BINDING /* specified binding string */
};
@@ -34,7 +36,7 @@ struct libnet_RpcConnect {
enum libnet_RpcConnect_level level;
struct {
- const char *domain_name;
+ const char *name;
const char *binding;
const struct dcerpc_interface_table *dcerpc_iface;
} in;
diff --git a/source4/libnet/libnet_share.c b/source4/libnet/libnet_share.c
index 9422cdd306..0f5a3aeb52 100644
--- a/source4/libnet/libnet_share.c
+++ b/source4/libnet/libnet_share.c
@@ -30,10 +30,16 @@ NTSTATUS libnet_ListShares(struct libnet_context *ctx,
struct srvsvc_NetShareEnumAll s;
uint32_t resume_handle;
struct srvsvc_NetShareCtr0 ctr0;
+ struct srvsvc_NetShareCtr1 ctr1;
+ struct srvsvc_NetShareCtr2 ctr2;
+ struct srvsvc_NetShareCtr501 ctr501;
+ struct srvsvc_NetShareCtr502 ctr502;
- c.level = LIBNET_RPC_CONNECT_SERVER;
- c.in.domain_name = r->in.server_name;
- c.in.dcerpc_iface = &dcerpc_table_srvsvc;
+ c.level = LIBNET_RPC_CONNECT_SERVER;
+ c.in.name = r->in.server_name;
+ c.in.dcerpc_iface = &dcerpc_table_srvsvc;
+
+ s.in.server_unc = talloc_asprintf(mem_ctx, "\\\\%s", c.in.name);
status = libnet_RpcConnect(ctx, mem_ctx, &c);
if (!NT_STATUS_IS_OK(status)) {
@@ -46,11 +52,36 @@ NTSTATUS libnet_ListShares(struct libnet_context *ctx,
}
s.in.level = r->in.level;
- s.in.ctr.ctr0 = &ctr0;
+ switch (s.in.level) {
+ case 0:
+ s.in.ctr.ctr0 = &ctr0;
+ ZERO_STRUCT(ctr0);
+ break;
+ case 1:
+ s.in.ctr.ctr1 = &ctr1;
+ ZERO_STRUCT(ctr1);
+ break;
+ case 2:
+ s.in.ctr.ctr2 = &ctr2;
+ ZERO_STRUCT(ctr2);
+ break;
+ case 501:
+ s.in.ctr.ctr501 = &ctr501;
+ ZERO_STRUCT(ctr501);
+ break;
+ case 502:
+ s.in.ctr.ctr502 = &ctr502;
+ ZERO_STRUCT(ctr502);
+ break;
+ default:
+ r->out.error_string = talloc_asprintf(mem_ctx,
+ "libnet_ListShares: Invalid info level requested: %d\n",
+ s.in.level);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
s.in.max_buffer = ~0;
s.in.resume_handle = &resume_handle;
- ZERO_STRUCT(ctr0);
status = dcerpc_srvsvc_NetShareEnumAll(c.out.dcerpc_pipe, mem_ctx, &s);
@@ -63,6 +94,9 @@ NTSTATUS libnet_ListShares(struct libnet_context *ctx,
}
if (!W_ERROR_IS_OK(s.out.result) && !W_ERROR_EQUAL(s.out.result, WERR_MORE_DATA)) {
+ r->out.error_string = talloc_asprintf(mem_ctx,
+ "srvsvc_NetShareEnumAll on server '%s' failed: %s",
+ r->in.server_name, win_errstr(s.out.result));
goto disconnect;
}
@@ -82,9 +116,9 @@ NTSTATUS libnet_AddShare(struct libnet_context *ctx,
struct libnet_RpcConnect c;
struct srvsvc_NetShareAdd s;
- c.level = LIBNET_RPC_CONNECT_SERVER;
- c.in.domain_name = r->in.server_name;
- c.in.dcerpc_iface = &dcerpc_table_srvsvc;
+ c.level = LIBNET_RPC_CONNECT_SERVER;
+ c.in.name = r->in.server_name;
+ c.in.dcerpc_iface = &dcerpc_table_srvsvc;
status = libnet_RpcConnect(ctx, mem_ctx, &c);
if (!NT_STATUS_IS_OK(status)) {
@@ -121,9 +155,9 @@ NTSTATUS libnet_DelShare(struct libnet_context *ctx,
struct libnet_RpcConnect c;
struct srvsvc_NetShareDel s;
- c.level = LIBNET_RPC_CONNECT_SERVER;
- c.in.domain_name = r->in.server_name;
- c.in.dcerpc_iface = &dcerpc_table_srvsvc;
+ c.level = LIBNET_RPC_CONNECT_SERVER;
+ c.in.name = r->in.server_name;
+ c.in.dcerpc_iface = &dcerpc_table_srvsvc;
status = libnet_RpcConnect(ctx, mem_ctx, &c);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/libnet/libnet_time.c b/source4/libnet/libnet_time.c
index 7d480a5348..c7f8c79db5 100644
--- a/source4/libnet/libnet_time.c
+++ b/source4/libnet/libnet_time.c
@@ -33,9 +33,9 @@ static NTSTATUS libnet_RemoteTOD_srvsvc(struct libnet_context *ctx, TALLOC_CTX *
struct tm tm;
/* prepare connect to the SRVSVC pipe of a timeserver */
- c.level = LIBNET_RPC_CONNECT_SERVER;
- c.in.domain_name = r->srvsvc.in.server_name;
- c.in.dcerpc_iface = &dcerpc_table_srvsvc;
+ c.level = LIBNET_RPC_CONNECT_SERVER;
+ c.in.name = r->srvsvc.in.server_name;
+ c.in.dcerpc_iface = &dcerpc_table_srvsvc;
/* 1. connect to the SRVSVC pipe of a timeserver */
status = libnet_RpcConnect(ctx, mem_ctx, &c);
@@ -47,7 +47,7 @@ static NTSTATUS libnet_RemoteTOD_srvsvc(struct libnet_context *ctx, TALLOC_CTX *
}
/* prepare srvsvc_NetrRemoteTOD */
- tod.in.server_unc = talloc_asprintf(mem_ctx, "\\%s", c.in.domain_name);
+ tod.in.server_unc = talloc_asprintf(mem_ctx, "\\%s", c.in.name);
/* 2. try srvsvc_NetRemoteTOD */
status = dcerpc_srvsvc_NetRemoteTOD(c.out.dcerpc_pipe, mem_ctx, &tod);
diff --git a/source4/libnet/libnet_user.c b/source4/libnet/libnet_user.c
index 629fbf8e05..50cb14d290 100644
--- a/source4/libnet/libnet_user.c
+++ b/source4/libnet/libnet_user.c
@@ -27,23 +27,13 @@ NTSTATUS libnet_CreateUser(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
{
NTSTATUS status;
struct libnet_RpcConnect cn;
- struct libnet_Lookup fp;
struct libnet_rpc_domain_open dom_io;
struct libnet_rpc_useradd user_io;
- const char *address;
- /* find domain pdc */
- fp.in.hostname = r->in.domain_name;
- fp.in.methods = NULL;
- fp.out.address = &address;
-
- status = libnet_LookupPdc(ctx, mem_ctx, &fp);
- if (!NT_STATUS_IS_OK(status)) return status;
-
- /* connect rpc service of remote server */
- cn.level = LIBNET_RPC_CONNECT_SERVER;
- cn.in.domain_name = talloc_strdup(mem_ctx, *fp.out.address);
- cn.in.dcerpc_iface = &dcerpc_table_samr;
+ /* connect rpc service of remote DC */
+ cn.level = LIBNET_RPC_CONNECT_PDC;
+ cn.in.name = talloc_strdup(mem_ctx, r->in.domain_name);
+ cn.in.dcerpc_iface = &dcerpc_table_samr;
status = libnet_RpcConnect(ctx, mem_ctx, &cn);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/libnet/libnet_vampire.c b/source4/libnet/libnet_vampire.c
index d9c25d053e..dc271ba577 100644
--- a/source4/libnet/libnet_vampire.c
+++ b/source4/libnet/libnet_vampire.c
@@ -210,7 +210,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
/* Setup schannel */
nt_status = dcerpc_pipe_connect_b(samsync_ctx, &p, b,
- &dcerpc_table_netlogon,
+ &dcerpc_table_netlogon,
machine_account, ctx->event_ctx);
if (!NT_STATUS_IS_OK(nt_status)) {