diff options
Diffstat (limited to 'source4/libnet')
-rw-r--r-- | source4/libnet/config.mk | 2 | ||||
-rw-r--r-- | source4/libnet/libnet_join.c | 22 | ||||
-rw-r--r-- | source4/libnet/libnet_lookup.c | 48 | ||||
-rw-r--r-- | source4/libnet/libnet_lookup.h | 12 | ||||
-rw-r--r-- | source4/libnet/libnet_passwd.c | 8 | ||||
-rw-r--r-- | source4/libnet/libnet_rpc.c | 45 | ||||
-rw-r--r-- | source4/libnet/libnet_rpc.h | 4 | ||||
-rw-r--r-- | source4/libnet/libnet_share.c | 56 | ||||
-rw-r--r-- | source4/libnet/libnet_time.c | 8 | ||||
-rw-r--r-- | source4/libnet/libnet_user.c | 18 | ||||
-rw-r--r-- | source4/libnet/libnet_vampire.c | 2 |
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)) { |