summaryrefslogtreecommitdiff
path: root/source4/librpc/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'source4/librpc/rpc')
-rw-r--r--source4/librpc/rpc/dcerpc_auth.c8
-rw-r--r--source4/librpc/rpc/dcerpc_schannel.c125
-rw-r--r--source4/librpc/rpc/dcerpc_smb.c16
-rw-r--r--source4/librpc/rpc/dcerpc_util.c207
4 files changed, 194 insertions, 162 deletions
diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c
index 1bcf4224c4..ac74788ba6 100644
--- a/source4/librpc/rpc/dcerpc_auth.c
+++ b/source4/librpc/rpc/dcerpc_auth.c
@@ -143,6 +143,7 @@ done:
*/
NTSTATUS dcerpc_bind_auth_password(struct dcerpc_pipe *p,
const char *uuid, uint_t version,
+ const char *workstation,
const char *domain,
const char *username,
const char *password,
@@ -161,6 +162,13 @@ NTSTATUS dcerpc_bind_auth_password(struct dcerpc_pipe *p,
return status;
}
+ status = gensec_set_workstation(p->conn->security_state.generic_state, workstation);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to start set GENSEC client workstation name to %s: %s\n",
+ workstation, nt_errstr(status)));
+ return status;
+ }
+
status = gensec_set_domain(p->conn->security_state.generic_state, domain);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n",
diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c
index d99d43ad58..170ddee1f3 100644
--- a/source4/librpc/rpc/dcerpc_schannel.c
+++ b/source4/librpc/rpc/dcerpc_schannel.c
@@ -33,7 +33,6 @@ struct dcerpc_schannel_state {
enum schannel_position state;
struct schannel_state *schannel_state;
struct creds_CredentialState *creds;
- char *account_name;
};
/*
@@ -104,7 +103,8 @@ static NTSTATUS dcerpc_schannel_update(struct gensec_security *gensec_security,
NTSTATUS status;
struct schannel_bind bind_schannel;
struct schannel_bind_ack bind_schannel_ack;
- const char *account_name;
+ const char *workstation;
+ const char *domain;
*out = data_blob(NULL, 0);
switch (gensec_security->gensec_role) {
@@ -114,7 +114,8 @@ static NTSTATUS dcerpc_schannel_update(struct gensec_security *gensec_security,
return NT_STATUS_OK;
}
- status = schannel_start(&dce_schan_state->schannel_state,
+ status = schannel_start(dce_schan_state,
+ &dce_schan_state->schannel_state,
dce_schan_state->creds->session_key,
True);
if (!NT_STATUS_IS_OK(status)) {
@@ -130,11 +131,11 @@ static NTSTATUS dcerpc_schannel_update(struct gensec_security *gensec_security,
bind_schannel.u.info23.domain = gensec_security->user.domain;
bind_schannel.u.info23.account_name = gensec_security->user.name;
bind_schannel.u.info23.dnsdomain = str_format_nbt_domain(out_mem_ctx, fulldomainname);
- bind_schannel.u.info23.workstation = str_format_nbt_domain(out_mem_ctx, gensec_security->user.name);
+ bind_schannel.u.info23.workstation = str_format_nbt_domain(out_mem_ctx, gensec_get_workstation(gensec_security));
#else
bind_schannel.bind_type = 3;
bind_schannel.u.info3.domain = gensec_security->user.domain;
- bind_schannel.u.info3.account_name = gensec_security->user.name;
+ bind_schannel.u.info3.workstation = gensec_get_workstation(gensec_security);
#endif
status = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel,
@@ -163,27 +164,29 @@ static NTSTATUS dcerpc_schannel_update(struct gensec_security *gensec_security,
}
if (bind_schannel.bind_type == 23) {
- account_name = bind_schannel.u.info23.account_name;
+ workstation = bind_schannel.u.info23.workstation;
+ domain = bind_schannel.u.info23.domain;
} else {
- account_name = bind_schannel.u.info3.account_name;
+ workstation = bind_schannel.u.info3.workstation;
+ domain = bind_schannel.u.info3.domain;
}
/* pull the session key for this client */
- status = schannel_fetch_session_key(out_mem_ctx, account_name, &dce_schan_state->creds);
+ status = schannel_fetch_session_key(out_mem_ctx, workstation,
+ domain, &dce_schan_state->creds);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("Could not find session key for attempted schannel connection on %s: %s\n",
- account_name, nt_errstr(status)));
+ DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n",
+ workstation, nt_errstr(status)));
return status;
}
- dce_schan_state->account_name = talloc_strdup(dce_schan_state, account_name);
-
/* start up the schannel server code */
- status = schannel_start(&dce_schan_state->schannel_state,
+ status = schannel_start(dce_schan_state,
+ &dce_schan_state->schannel_state,
dce_schan_state->creds->session_key, False);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("Could not initialise schannel state for account %s: %s\n",
- account_name, nt_errstr(status)));
+ DEBUG(3, ("Could not initialise schannel state from client %s: %s\n",
+ workstation, nt_errstr(status)));
return status;
}
talloc_steal(dce_schan_state, dce_schan_state->schannel_state);
@@ -195,8 +198,8 @@ static NTSTATUS dcerpc_schannel_update(struct gensec_security *gensec_security,
status = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack,
(ndr_push_flags_fn_t)ndr_push_schannel_bind_ack);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("Could not return schannel bind ack for account %s: %s\n",
- account_name, nt_errstr(status)));
+ DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n",
+ workstation, nt_errstr(status)));
return status;
}
@@ -248,18 +251,6 @@ NTSTATUS dcerpc_schannel_creds(struct gensec_security *gensec_security,
}
-/*
- end crypto state
-*/
-static int dcerpc_schannel_destroy(void *ptr)
-{
- struct dcerpc_schannel_state *dce_schan_state = ptr;
-
- schannel_end(&dce_schan_state->schannel_state);
-
- return 0;
-}
-
static NTSTATUS dcerpc_schannel_start(struct gensec_security *gensec_security)
{
struct dcerpc_schannel_state *dce_schan_state;
@@ -272,8 +263,6 @@ static NTSTATUS dcerpc_schannel_start(struct gensec_security *gensec_security)
dce_schan_state->state = DCERPC_SCHANNEL_STATE_START;
gensec_security->private_data = dce_schan_state;
- talloc_set_destructor(dce_schan_state, dcerpc_schannel_destroy);
-
return NT_STATUS_OK;
}
@@ -306,6 +295,7 @@ static NTSTATUS dcerpc_schannel_client_start(struct gensec_security *gensec_secu
get a schannel key using a netlogon challenge on a secondary pipe
*/
static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
+ const char *workstation,
const char *domain,
const char *username,
const char *password,
@@ -313,13 +303,15 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
struct creds_CredentialState *creds)
{
NTSTATUS status;
+ struct dcerpc_binding *b;
struct dcerpc_pipe *p2;
struct netr_ServerReqChallenge r;
struct netr_ServerAuthenticate2 a;
struct netr_Credential credentials1, credentials2, credentials3;
struct samr_Password mach_pwd;
- const char *workgroup, *workstation;
+ const char *workgroup;
uint32_t negotiate_flags;
+ TALLOC_CTX *tmp_ctx;
if (p->conn->flags & DCERPC_SCHANNEL_128) {
negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
@@ -327,20 +319,45 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
}
- workstation = username;
workgroup = domain;
+ tmp_ctx = talloc_new(NULL);
+
/*
step 1 - establish a netlogon connection, with no authentication
*/
- status = dcerpc_secondary_connection(p, &p2,
- DCERPC_NETLOGON_NAME,
- DCERPC_NETLOGON_UUID,
- DCERPC_NETLOGON_VERSION);
+
+ /* Find the original binding string */
+ status = dcerpc_parse_binding(tmp_ctx, p->conn->binding_string, &b);
if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("Failed to parse dcerpc binding '%s'\n", p->conn->binding_string));
+ talloc_free(tmp_ctx);
return status;
}
+ /* Make binding string for netlogon, not the other pipe */
+ status = dcerpc_epm_map_binding(tmp_ctx, b, DCERPC_NETLOGON_UUID, DCERPC_NETLOGON_VERSION);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("Failed to map DCERPC/TCP NCACN_NP pipe for '%s' - %s\n",
+ DCERPC_NETLOGON_UUID, nt_errstr(status)));
+ talloc_free(p);
+ return status;
+ }
+
+ status = dcerpc_secondary_connection(p, &p2, b);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+
+ talloc_free(tmp_ctx);
+
+ status = dcerpc_bind_auth_none(p2, DCERPC_NETLOGON_UUID,
+ DCERPC_NETLOGON_VERSION);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(p2);
+ return status;
+ }
/*
step 2 - request a netlogon challenge
@@ -361,11 +378,13 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
step 3 - authenticate on the netlogon pipe
*/
E_md4hash(password, mach_pwd.hash);
- creds_client_init(creds, &credentials1, &credentials2, &mach_pwd, &credentials3,
+ creds_client_init(creds, &credentials1, &credentials2,
+ workstation, domain, username,
+ &mach_pwd, &credentials3,
negotiate_flags);
a.in.server_name = r.in.server_name;
- a.in.account_name = talloc_asprintf(p, "%s$", workstation);
+ a.in.account_name = username;
a.in.secure_channel_type = chan_type;
a.in.computer_name = workstation;
a.in.negotiate_flags = &negotiate_flags;
@@ -398,9 +417,6 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
*/
NTSTATUS dcerpc_bind_auth_schannel_withkey(struct dcerpc_pipe *p,
const char *uuid, uint_t version,
- const char *domain,
- const char *username,
- const char *password,
struct creds_CredentialState *creds)
{
NTSTATUS status;
@@ -411,17 +427,28 @@ NTSTATUS dcerpc_bind_auth_schannel_withkey(struct dcerpc_pipe *p,
return status;
}
- status = gensec_set_username(p->conn->security_state.generic_state, username);
+ status = gensec_set_workstation(p->conn->security_state.generic_state, creds->computer_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to set schannel workstation to %s: %s\n",
+ creds->computer_name, nt_errstr(status)));
+ talloc_free(p->conn->security_state.generic_state);
+ p->conn->security_state.generic_state = NULL;
+ return status;
+ }
+
+ status = gensec_set_username(p->conn->security_state.generic_state, creds->account_name);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to set schannel username to %s: %s\n", username, nt_errstr(status)));
+ DEBUG(1, ("Failed to set schannel username to %s: %s\n",
+ creds->account_name, nt_errstr(status)));
talloc_free(p->conn->security_state.generic_state);
p->conn->security_state.generic_state = NULL;
return status;
}
- status = gensec_set_domain(p->conn->security_state.generic_state, domain);
+ status = gensec_set_domain(p->conn->security_state.generic_state, creds->domain);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to set schannel domain to %s: %s\n", domain, nt_errstr(status)));
+ DEBUG(1, ("Failed to set schannel domain to %s: %s\n",
+ creds->domain, nt_errstr(status)));
talloc_free(p->conn->security_state.generic_state);
p->conn->security_state.generic_state = NULL;
return status;
@@ -456,6 +483,7 @@ NTSTATUS dcerpc_bind_auth_schannel_withkey(struct dcerpc_pipe *p,
NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p,
const char *uuid, uint_t version,
+ const char *workstation,
const char *domain,
const char *username,
const char *password)
@@ -477,6 +505,7 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p,
}
status = dcerpc_schannel_key(p, domain,
+ workstation,
username,
password,
chan_type,
@@ -488,9 +517,7 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p,
return status;
}
- return dcerpc_bind_auth_schannel_withkey(p, uuid, version, domain,
- username, password,
- creds);
+ return dcerpc_bind_auth_schannel_withkey(p, uuid, version, creds);
}
static BOOL dcerpc_schannel_have_feature(struct gensec_security *gensec_security,
diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c
index aa2d0bf20f..1a5a31c330 100644
--- a/source4/librpc/rpc/dcerpc_smb.c
+++ b/source4/librpc/rpc/dcerpc_smb.c
@@ -375,7 +375,19 @@ NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_connection *c,
struct smb_private *smb;
NTSTATUS status;
union smb_open io;
+ char *pipe_name_talloc;
+ if (!strncasecmp(pipe_name, "/pipe/", 6) ||
+ !strncasecmp(pipe_name, "\\pipe\\", 6)) {
+ pipe_name += 6;
+ }
+
+ if (pipe_name[0] != '\\') {
+ pipe_name_talloc = talloc_asprintf(NULL, "\\%s", pipe_name);
+ } else {
+ pipe_name_talloc = talloc_strdup(NULL, pipe_name);
+ }
+
io.ntcreatex.level = RAW_OPEN_NTCREATEX;
io.ntcreatex.in.flags = 0;
io.ntcreatex.in.root_fid = 0;
@@ -394,10 +406,12 @@ NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_connection *c,
io.ntcreatex.in.create_options = 0;
io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
io.ntcreatex.in.security_flags = 0;
- io.ntcreatex.in.fname = pipe_name;
+ io.ntcreatex.in.fname = pipe_name_talloc;
status = smb_raw_open(tree, tree, &io);
+ talloc_free(pipe_name_talloc);
+
if (!NT_STATUS_IS_OK(status)) {
return status;
}
diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c
index 7b753d1b30..91e6ea9397 100644
--- a/source4/librpc/rpc/dcerpc_util.c
+++ b/source4/librpc/rpc/dcerpc_util.c
@@ -323,12 +323,18 @@ const char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_bindi
/*
parse a binding string into a dcerpc_binding structure
*/
-NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_binding *b)
+NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_binding **b_out)
{
+ struct dcerpc_binding *b;
char *options, *type;
char *p;
int i, j, comma_count;
+ b = talloc(mem_ctx, struct dcerpc_binding);
+ if (!b) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
p = strchr(s, '@');
if (p && PTR_DIFF(p, s) == 36) { /* 36 is the length of a UUID */
@@ -373,14 +379,14 @@ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_
p = strchr(s, '[');
if (p) {
- b->host = talloc_strndup(mem_ctx, s, PTR_DIFF(p, s));
+ b->host = talloc_strndup(b, s, PTR_DIFF(p, s));
options = talloc_strdup(mem_ctx, p+1);
if (options[strlen(options)-1] != ']') {
return NT_STATUS_INVALID_PARAMETER;
}
options[strlen(options)-1] = 0;
} else {
- b->host = talloc_strdup(mem_ctx, s);
+ b->host = talloc_strdup(b, s);
options = NULL;
}
@@ -393,18 +399,19 @@ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_
b->endpoint = NULL;
if (!options) {
+ *b_out = b;
return NT_STATUS_OK;
}
comma_count = count_chars(options, ',');
- b->options = talloc_array(mem_ctx, const char *, comma_count+2);
+ b->options = talloc_array(b, const char *, comma_count+2);
if (!b->options) {
return NT_STATUS_NO_MEMORY;
}
for (i=0; (p = strchr(options, ',')); i++) {
- b->options[i] = talloc_strndup(mem_ctx, options, PTR_DIFF(p, options));
+ b->options[i] = talloc_strndup(b, options, PTR_DIFF(p, options));
if (!b->options[i]) {
return NT_STATUS_NO_MEMORY;
}
@@ -441,6 +448,7 @@ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_
if (b->options[0] == NULL)
b->options = NULL;
+ *b_out = b;
return NT_STATUS_OK;
}
@@ -657,9 +665,13 @@ enum dcerpc_transport_t dcerpc_transport_by_tower(struct epm_tower *tower)
return -1;
}
-NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, struct epm_tower *tower, struct dcerpc_binding *binding)
+NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, struct epm_tower *tower, struct dcerpc_binding **b_out)
{
NTSTATUS status;
+ struct dcerpc_binding *binding;
+
+ binding = talloc(mem_ctx, struct dcerpc_binding);
+ NT_STATUS_HAVE_NO_MEMORY(binding);
ZERO_STRUCT(binding->object);
binding->options = NULL;
@@ -699,6 +711,7 @@ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, struct epm_tower *tower,
if (tower->num_floors >= 5) {
binding->host = dcerpc_floor_get_rhs_data(mem_ctx, &tower->floors[4]);
}
+ *b_out = binding;
return NT_STATUS_OK;
}
@@ -773,7 +786,7 @@ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding *
}
NTSTATUS dcerpc_epm_map_binding(TALLOC_CTX *mem_ctx, struct dcerpc_binding *binding,
- const char *uuid, uint_t version)
+ const char *uuid, uint_t version)
{
struct dcerpc_pipe *p;
NTSTATUS status;
@@ -781,42 +794,51 @@ NTSTATUS dcerpc_epm_map_binding(TALLOC_CTX *mem_ctx, struct dcerpc_binding *bind
struct policy_handle handle;
struct GUID guid;
struct epm_twr_t twr, *twr_r;
- struct dcerpc_binding epmapper_binding;
+ struct dcerpc_binding *epmapper_binding;
const struct dcerpc_interface_table *table = idl_iface_by_uuid(uuid);
int i;
/* First, check if there is a default endpoint specified in the IDL */
if (table) {
- struct dcerpc_binding default_binding;
+ struct dcerpc_binding *default_binding;
- binding->authservice = talloc_strdup(mem_ctx, table->authservices->names[0]);
+ binding->authservice = talloc_strdup(binding, table->authservices->names[0]);
/* Find one of the default pipes for this interface */
for (i = 0; i < table->endpoints->count; i++) {
status = dcerpc_parse_binding(mem_ctx, table->endpoints->names[i], &default_binding);
- if (NT_STATUS_IS_OK(status) && default_binding.transport == binding->transport && default_binding.endpoint) {
- binding->endpoint = talloc_strdup(mem_ctx, default_binding.endpoint);
- return NT_STATUS_OK;
+ if (NT_STATUS_IS_OK(status)) {
+ if (default_binding->transport == binding->transport && default_binding->endpoint) {
+ binding->endpoint = talloc_reference(binding, default_binding->endpoint);
+ talloc_free(default_binding);
+ return NT_STATUS_OK;
+ } else {
+ talloc_free(default_binding);
+ }
}
}
}
+ epmapper_binding = talloc_zero(mem_ctx, struct dcerpc_binding);
+ if (!epmapper_binding) {
+ return NT_STATUS_NO_MEMORY;
+ }
- ZERO_STRUCT(epmapper_binding);
- epmapper_binding.transport = binding->transport;
- epmapper_binding.host = binding->host;
- epmapper_binding.options = NULL;
- epmapper_binding.flags = 0;
- epmapper_binding.endpoint = NULL;
- epmapper_binding.authservice = NULL;
+ epmapper_binding->transport = binding->transport;
+ epmapper_binding->host = talloc_reference(epmapper_binding,
+ binding->host);
+ epmapper_binding->options = NULL;
+ epmapper_binding->flags = 0;
+ epmapper_binding->endpoint = NULL;
+ epmapper_binding->authservice = NULL;
status = dcerpc_pipe_connect_b(&p,
- &epmapper_binding,
- DCERPC_EPMAPPER_UUID,
- DCERPC_EPMAPPER_VERSION,
- NULL, NULL, NULL);
+ epmapper_binding,
+ DCERPC_EPMAPPER_UUID,
+ DCERPC_EPMAPPER_VERSION,
+ NULL, NULL, NULL, NULL);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -866,7 +888,7 @@ NTSTATUS dcerpc_epm_map_binding(TALLOC_CTX *mem_ctx, struct dcerpc_binding *bind
return NT_STATUS_PORT_UNREACHABLE;
}
- binding->endpoint = dcerpc_floor_get_rhs_data(mem_ctx, &twr_r->tower.floors[3]);
+ binding->endpoint = talloc_reference(binding, dcerpc_floor_get_rhs_data(mem_ctx, &twr_r->tower.floors[3]));
dcerpc_pipe_close(p);
@@ -877,13 +899,14 @@ NTSTATUS dcerpc_epm_map_binding(TALLOC_CTX *mem_ctx, struct dcerpc_binding *bind
/*
perform an authenticated bind if needed
*/
-static NTSTATUS dcerpc_pipe_auth(struct dcerpc_pipe *p,
- struct dcerpc_binding *binding,
- const char *pipe_uuid,
- uint32_t pipe_version,
- const char *domain,
- const char *username,
- const char *password)
+NTSTATUS dcerpc_pipe_auth(struct dcerpc_pipe *p,
+ struct dcerpc_binding *binding,
+ const char *pipe_uuid,
+ uint32_t pipe_version,
+ const char *workstation,
+ const char *domain,
+ const char *username,
+ const char *password)
{
NTSTATUS status;
p->conn->flags = binding->flags;
@@ -893,7 +916,8 @@ static NTSTATUS dcerpc_pipe_auth(struct dcerpc_pipe *p,
if (username && username[0] && (binding->flags & DCERPC_SCHANNEL_ANY)) {
status = dcerpc_bind_auth_schannel(p, pipe_uuid, pipe_version,
- domain, username, password);
+ domain, workstation,
+ username, password);
} else if (username && username[0]) {
uint8_t auth_type;
if (binding->flags & DCERPC_AUTH_SPNEGO) {
@@ -905,6 +929,7 @@ static NTSTATUS dcerpc_pipe_auth(struct dcerpc_pipe *p,
}
status = dcerpc_bind_auth_password(p, pipe_uuid, pipe_version,
+ workstation,
domain, username, password,
auth_type,
binding->authservice);
@@ -925,6 +950,7 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **pp,
struct dcerpc_binding *binding,
const char *pipe_uuid,
uint32_t pipe_version,
+ const char *workstation,
const char *domain,
const char *username,
const char *password)
@@ -957,23 +983,14 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **pp,
pipe_name = binding->endpoint;
- if (!strncasecmp(pipe_name, "/pipe/", 6) ||
- !strncasecmp(pipe_name, "\\pipe\\", 6)) {
- pipe_name += 6;
- }
-
- if (pipe_name[0] != '\\') {
- pipe_name = talloc_asprintf(tmp_ctx, "\\%s", pipe_name);
- }
-
if (!username || !username[0] ||
(binding->flags & DCERPC_SCHANNEL_ANY)) {
- status = smbcli_full_connection(p->conn, &cli, lp_netbios_name(),
+ status = smbcli_full_connection(p->conn, &cli, workstation,
binding->host,
"ipc$", NULL,
"", "", NULL);
} else {
- status = smbcli_full_connection(p->conn, &cli, lp_netbios_name(),
+ status = smbcli_full_connection(p->conn, &cli, workstation,
binding->host,
"ipc$", NULL,
username, domain,
@@ -995,12 +1012,6 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **pp,
if (!(binding->flags & DCERPC_AUTH_OPTIONS)) {
username = NULL;
}
-
- status = dcerpc_pipe_auth(p, binding, pipe_uuid, pipe_version, domain, username, password);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(p);
- return status;
- }
(*pp) = p;
talloc_free(tmp_ctx);
@@ -1013,10 +1024,7 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **pp,
static NTSTATUS dcerpc_pipe_connect_ncalrpc(struct dcerpc_pipe **pp,
struct dcerpc_binding *binding,
const char *pipe_uuid,
- uint32_t pipe_version,
- const char *domain,
- const char *username,
- const char *password)
+ uint32_t pipe_version)
{
NTSTATUS status;
struct dcerpc_pipe *p;
@@ -1050,12 +1058,6 @@ static NTSTATUS dcerpc_pipe_connect_ncalrpc(struct dcerpc_pipe **pp,
return status;
}
- status = dcerpc_pipe_auth(p, binding, pipe_uuid, pipe_version, domain, username, password);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(p);
- return status;
- }
-
(*pp) = p;
talloc_free(tmp_ctx);
@@ -1069,10 +1071,7 @@ static NTSTATUS dcerpc_pipe_connect_ncalrpc(struct dcerpc_pipe **pp,
static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream(struct dcerpc_pipe **pp,
struct dcerpc_binding *binding,
const char *pipe_uuid,
- uint32_t pipe_version,
- const char *domain,
- const char *username,
- const char *password)
+ uint32_t pipe_version)
{
NTSTATUS status;
struct dcerpc_pipe *p;
@@ -1097,12 +1096,6 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream(struct dcerpc_pipe **pp,
return status;
}
- status = dcerpc_pipe_auth(p, binding, pipe_uuid, pipe_version, domain, username, password);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(p);
- return status;
- }
-
(*pp) = p;
return status;
@@ -1113,10 +1106,7 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream(struct dcerpc_pipe **pp,
static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **pp,
struct dcerpc_binding *binding,
const char *pipe_uuid,
- uint32_t pipe_version,
- const char *domain,
- const char *username,
- const char *password)
+ uint32_t pipe_version)
{
NTSTATUS status;
uint32_t port = 0;
@@ -1153,12 +1143,6 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **pp,
return status;
}
- status = dcerpc_pipe_auth(p, binding, pipe_uuid, pipe_version, domain, username, password);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(p);
- return status;
- }
-
(*pp) = p;
talloc_free(tmp_ctx);
@@ -1172,33 +1156,42 @@ NTSTATUS dcerpc_pipe_connect_b(struct dcerpc_pipe **pp,
struct dcerpc_binding *binding,
const char *pipe_uuid,
uint32_t pipe_version,
+ const char *workstation,
const char *domain,
const char *username,
const char *password)
{
NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
-
+
switch (binding->transport) {
case NCACN_NP:
status = dcerpc_pipe_connect_ncacn_np(pp, binding, pipe_uuid, pipe_version,
- domain, username, password);
+ workstation, domain, username, password);
break;
case NCACN_IP_TCP:
- status = dcerpc_pipe_connect_ncacn_ip_tcp(pp, binding, pipe_uuid, pipe_version,
- domain, username, password);
+ status = dcerpc_pipe_connect_ncacn_ip_tcp(pp, binding, pipe_uuid, pipe_version);
break;
case NCACN_UNIX_STREAM:
- status = dcerpc_pipe_connect_ncacn_unix_stream(pp, binding, pipe_uuid, pipe_version,
- domain, username, password);
+ status = dcerpc_pipe_connect_ncacn_unix_stream(pp, binding, pipe_uuid, pipe_version);
break;
case NCALRPC:
- status = dcerpc_pipe_connect_ncalrpc(pp, binding, pipe_uuid, pipe_version,
- domain, username, password);
+ status = dcerpc_pipe_connect_ncalrpc(pp, binding, pipe_uuid, pipe_version);
break;
default:
return NT_STATUS_NOT_SUPPORTED;
}
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = dcerpc_pipe_auth(*pp, binding, pipe_uuid, pipe_version, workstation, domain, username, password);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(*pp);
+ *pp = NULL;
+ return status;
+ }
+
return status;
}
@@ -1209,15 +1202,19 @@ NTSTATUS dcerpc_pipe_connect(struct dcerpc_pipe **pp,
const char *binding,
const char *pipe_uuid,
uint32_t pipe_version,
+ const char *workstation,
const char *domain,
const char *username,
const char *password)
{
- struct dcerpc_binding b;
+ struct dcerpc_binding *b;
NTSTATUS status;
TALLOC_CTX *tmp_ctx;
tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return NT_STATUS_NO_MEMORY;
+ }
status = dcerpc_parse_binding(tmp_ctx, binding, &b);
if (!NT_STATUS_IS_OK(status)) {
@@ -1226,9 +1223,10 @@ NTSTATUS dcerpc_pipe_connect(struct dcerpc_pipe **pp,
return status;
}
- DEBUG(3,("Using binding %s\n", dcerpc_binding_string(tmp_ctx, &b)));
+ DEBUG(3,("Using binding %s\n", dcerpc_binding_string(tmp_ctx, b)));
- status = dcerpc_pipe_connect_b(pp, &b, pipe_uuid, pipe_version, domain, username, password);
+ status = dcerpc_pipe_connect_b(pp, b, pipe_uuid, pipe_version, workstation,
+ domain, username, password);
talloc_free(tmp_ctx);
@@ -1243,13 +1241,12 @@ NTSTATUS dcerpc_pipe_connect(struct dcerpc_pipe **pp,
will be on the same SMB connection, but use a new fnum
*/
NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p, struct dcerpc_pipe **p2,
- const char *pipe_name,
- const char *pipe_uuid,
- uint32_t pipe_version)
+ struct dcerpc_binding *b)
+
+
{
struct smbcli_tree *tree;
NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
- struct dcerpc_binding b;
(*p2) = dcerpc_pipe_init(p);
if (*p2 == NULL) {
@@ -1262,23 +1259,15 @@ NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p, struct dcerpc_pipe *
if (!tree) {
return NT_STATUS_INVALID_PARAMETER;
}
- status = dcerpc_pipe_open_smb((*p2)->conn, tree, pipe_name);
+ status = dcerpc_pipe_open_smb((*p2)->conn, tree, b->endpoint);
break;
case NCACN_IP_TCP:
- status = dcerpc_parse_binding(p, p->conn->binding_string, &b);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- status = dcerpc_pipe_open_tcp((*p2)->conn, b.host, atoi(b.endpoint));
+ status = dcerpc_pipe_open_tcp((*p2)->conn, b->host, atoi(b->endpoint));
break;
case NCALRPC:
- status = dcerpc_parse_binding(p, p->conn->binding_string, &b);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- status = dcerpc_pipe_open_pipe((*p2)->conn, b.endpoint);
+ status = dcerpc_pipe_open_pipe((*p2)->conn, b->endpoint);
break;
default:
@@ -1292,12 +1281,6 @@ NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p, struct dcerpc_pipe *
(*p2)->conn->flags = p->conn->flags;
- status = dcerpc_bind_auth_none(*p2, pipe_uuid, pipe_version);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(*p2);
- return status;
- }
-
return NT_STATUS_OK;
}