summaryrefslogtreecommitdiff
path: root/source4/librpc/rpc
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2006-05-07 19:55:14 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:05:43 -0500
commit7f0a396e3b4f02aea24d6e6d8d6123c5aa737248 (patch)
tree09883421ee80e52bda061bf9bd84b6e1d5f8b9f8 /source4/librpc/rpc
parente9c7016699c61b4d21341b639bbe4291dcd21872 (diff)
downloadsamba-7f0a396e3b4f02aea24d6e6d8d6123c5aa737248.tar.gz
samba-7f0a396e3b4f02aea24d6e6d8d6123c5aa737248.tar.bz2
samba-7f0a396e3b4f02aea24d6e6d8d6123c5aa737248.zip
r15504: Revert -r 15500 and -r 15503 until I'm awake, and can get my head
around the mess that is composite functions... Async might be all the rage, but it's bloody painful to debug. Andrew Bartlett (This used to be commit 756e1dad7ce54b83f8170db3434bfcfc4afe7e65)
Diffstat (limited to 'source4/librpc/rpc')
-rw-r--r--source4/librpc/rpc/dcerpc.c60
-rw-r--r--source4/librpc/rpc/dcerpc_connect.c5
-rw-r--r--source4/librpc/rpc/dcerpc_util.c131
3 files changed, 113 insertions, 83 deletions
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index adf67a7ba1..cd33d3d14b 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -490,20 +490,6 @@ static NTSTATUS dcerpc_map_reason(uint16_t reason)
}
/*
- map a fault reason to a NTSTATUS
-*/
-static NTSTATUS dcerpc_map_fault(uint32_t status)
-{
- switch (status) {
- case DCERPC_FAULT_OP_RNG_ERROR:
- return NT_STATUS_ILLEGAL_FUNCTION;
- case DCERPC_FAULT_ACCESS_DENIED:
- return NT_STATUS_ACCESS_DENIED;
- }
- return NT_STATUS_NET_WRITE_FAULT;
-}
-
-/*
mark the dcerpc connection dead. All outstanding requests get an error
*/
static void dcerpc_connection_dead(struct dcerpc_connection *conn, NTSTATUS status)
@@ -569,19 +555,27 @@ static void dcerpc_recv_data(struct dcerpc_connection *conn, DATA_BLOB *blob, NT
dcerpc_connection_dead(conn, status);
}
- if (conn->bind_private) {
- talloc_steal(conn->bind_private, blob->data);
- dcerpc_bind_recv_data(conn, &pkt);
- return;
- }
- if (conn->alter_private) {
- talloc_steal(conn->alter_private, blob->data);
- dcerpc_alter_recv_data(conn, &pkt);
- return;
- }
+ switch (pkt.ptype) {
+ case DCERPC_PKT_BIND_NAK:
+ case DCERPC_PKT_BIND_ACK:
+ if (conn->bind_private) {
+ talloc_steal(conn->bind_private, blob->data);
+ dcerpc_bind_recv_data(conn, &pkt);
+ }
+ break;
- /* assume its an ordinary request */
- dcerpc_request_recv_data(conn, blob, &pkt);
+ case DCERPC_PKT_ALTER_RESP:
+ if (conn->alter_private) {
+ talloc_steal(conn->alter_private, blob->data);
+ dcerpc_alter_recv_data(conn, &pkt);
+ }
+ break;
+
+ default:
+ /* assume its an ordinary request */
+ dcerpc_request_recv_data(conn, blob, &pkt);
+ break;
+ }
}
@@ -597,13 +591,6 @@ static void dcerpc_bind_recv_data(struct dcerpc_connection *conn, struct ncacn_p
/* mark the connection as not waiting for a bind reply */
conn->bind_private = NULL;
- if (pkt->ptype == DCERPC_PKT_FAULT) {
- DEBUG(2,("dcerpc: bind faulted: reason %s\n",
- dcerpc_errstr(c, pkt->u.fault.status)));
- composite_error(c, dcerpc_map_fault(pkt->u.fault.status));
- return;
- }
-
if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
DEBUG(2,("dcerpc: bind_nak reason %d\n",
pkt->u.bind_nak.reject_reason));
@@ -1541,13 +1528,6 @@ static void dcerpc_alter_recv_data(struct dcerpc_connection *conn, struct ncacn_
/* mark the connection as not waiting for a alter context reply */
conn->alter_private = NULL;
- if (pkt->ptype == DCERPC_PKT_FAULT) {
- DEBUG(2,("dcerpc: alter context faulted: reason %s\n",
- dcerpc_errstr(c, pkt->u.fault.status)));
- composite_error(c, dcerpc_map_fault(pkt->u.fault.status));
- return;
- }
-
if (pkt->ptype == DCERPC_PKT_ALTER_RESP &&
pkt->u.alter_resp.num_results == 1 &&
pkt->u.alter_resp.ctx_list[0].result != 0) {
diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c
index 66b0af178b..d69db51eb4 100644
--- a/source4/librpc/rpc/dcerpc_connect.c
+++ b/source4/librpc/rpc/dcerpc_connect.c
@@ -764,7 +764,7 @@ static void continue_pipe_auth(struct composite_context *ctx)
struct composite_context);
struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state);
- c->status = dcerpc_pipe_auth_recv(s, &s->pipe);
+ c->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe);
if (!composite_is_ok(c)) return;
composite_done(c);
@@ -1170,8 +1170,7 @@ NTSTATUS dcerpc_secondary_connection_recv(struct composite_context *c,
s = talloc_get_type(c->private_data, struct sec_conn_state);
if (NT_STATUS_IS_OK(status)) {
- talloc_steal(s->pipe, s->pipe2);
- *p2 = s->pipe2;
+ *p2 = talloc_steal(s->pipe, s->pipe2);
}
talloc_free(c);
diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c
index 5b341b9359..6c8ed7ecd8 100644
--- a/source4/librpc/rpc/dcerpc_util.c
+++ b/source4/librpc/rpc/dcerpc_util.c
@@ -976,12 +976,14 @@ struct pipe_auth_state {
struct dcerpc_binding *binding;
const struct dcerpc_interface_table *table;
struct cli_credentials *credentials;
- uint8_t auth_type;
- BOOL try_ntlm_fallback;
};
-static void continue_new_auth_bind(struct composite_context *ctx);
+static void continue_auth_schannel(struct composite_context *ctx);
+static void continue_auth(struct composite_context *ctx);
+static void continue_auth_none(struct composite_context *ctx);
+static void continue_ntlmssp_connection(struct composite_context *ctx);
+static void continue_spnego_after_wrong_pass(struct composite_context *ctx);
/*
@@ -1000,32 +1002,42 @@ static void continue_auth_schannel(struct composite_context *ctx)
/*
+ Stage 2 of pipe_auth: Receive result of authenticated bind request
+*/
+static void continue_auth(struct composite_context *ctx)
+{
+ struct composite_context *c = talloc_get_type(ctx->async.private_data,
+ struct composite_context);
+
+ c->status = dcerpc_bind_auth_recv(ctx);
+ if (!composite_is_ok(c)) return;
+
+ composite_done(c);
+}
+/*
Stage 2 of pipe_auth: Receive result of authenticated bind request, but handle fallbacks:
SPNEGO -> NTLMSSP
*/
-static void continue_recv_bind(struct composite_context *ctx)
+static void continue_auth_auto(struct composite_context *ctx)
{
- NTSTATUS status;
struct composite_context *c = talloc_get_type(ctx->async.private_data,
struct composite_context);
- struct pipe_auth_state *s = talloc_get_type(c->private_data, struct pipe_auth_state);
- status = dcerpc_bind_auth_recv(ctx);
- if (s->auth_type == DCERPC_AUTH_TYPE_SPNEGO
- && s->try_ntlm_fallback
- && NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
+ c->status = dcerpc_bind_auth_recv(ctx);
+ if (NT_STATUS_EQUAL(c->status, NT_STATUS_INVALID_PARAMETER)) {
+ struct pipe_auth_state *s = talloc_get_type(c->private_data, struct pipe_auth_state);
struct composite_context *sec_conn_req;
- s->try_ntlm_fallback = False;
- s->auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
+
/* send a request for secondary rpc connection */
sec_conn_req = dcerpc_secondary_connection_send(s->pipe,
s->binding);
if (composite_nomem(sec_conn_req, c)) return;
- composite_continue(c, sec_conn_req, continue_new_auth_bind, c);
+ composite_continue(c, sec_conn_req, continue_ntlmssp_connection, c);
return;
- } else if (s->auth_type == DCERPC_AUTH_TYPE_SPNEGO && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+ } else if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
+ struct pipe_auth_state *s = talloc_get_type(c->private_data, struct pipe_auth_state);
struct composite_context *sec_conn_req;
if (cli_credentials_wrong_password(s->credentials)) {
/* send a request for secondary rpc connection */
@@ -1033,12 +1045,9 @@ static void continue_recv_bind(struct composite_context *ctx)
s->binding);
if (composite_nomem(sec_conn_req, c)) return;
- composite_continue(c, sec_conn_req, continue_new_auth_bind, c);
-
- return;
+ composite_continue(c, sec_conn_req, continue_spnego_after_wrong_pass, c);
}
}
- c->status = status;
if (!composite_is_ok(c)) return;
@@ -1046,14 +1055,44 @@ static void continue_recv_bind(struct composite_context *ctx)
}
/*
- Stage 3 of pipe_auth (fallback to NTLMSSP case/SPNEGO password retry case):
-
- Receive secondary rpc connection (the first one can't be used any
- more, due to the bind nak) and perform authenticated bind request
+ Stage 3 of pipe_auth (fallback to NTLMSSP case): Receive secondary
+ rpc connection (the first one can't be used any more, due to the
+ bind nak) and perform authenticated bind request
+*/
+static void continue_ntlmssp_connection(struct composite_context *ctx)
+{
+ struct composite_context *c;
+ struct pipe_auth_state *s;
+ struct composite_context *auth_req;
+ struct dcerpc_pipe *p2;
+
+ c = talloc_get_type(ctx->async.private_data, struct composite_context);
+ s = talloc_get_type(c->private_data, struct pipe_auth_state);
+
+ /* receive secondary rpc connection */
+ c->status = dcerpc_secondary_connection_recv(ctx, &p2);
+ talloc_steal(s, p2);
+ talloc_steal(p2, s->pipe);
+ s->pipe = p2;
- Calls back to stage 2 to process the response.
+ if (!composite_is_ok(c)) return;
+
+ /* initiate a authenticated bind */
+ auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table,
+ s->credentials, DCERPC_AUTH_TYPE_NTLMSSP,
+ dcerpc_auth_level(s->pipe->conn),
+ s->table->authservices->names[0]);
+ if (composite_nomem(auth_req, c)) return;
+
+ composite_continue(c, auth_req, continue_auth, c);
+}
+
+/*
+ Stage 3 of pipe_auth (retry on wrong password): Receive secondary
+ rpc connection (the first one can't be used any more, due to the
+ bind nak) and perform authenticated bind request
*/
-static void continue_new_auth_bind(struct composite_context *ctx)
+static void continue_spnego_after_wrong_pass(struct composite_context *ctx)
{
struct composite_context *c;
struct pipe_auth_state *s;
@@ -1065,25 +1104,27 @@ static void continue_new_auth_bind(struct composite_context *ctx)
/* receive secondary rpc connection */
c->status = dcerpc_secondary_connection_recv(ctx, &p2);
+ talloc_steal(s, p2);
+ talloc_steal(p2, s->pipe);
s->pipe = p2;
if (!composite_is_ok(c)) return;
/* initiate a authenticated bind */
auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table,
- s->credentials, s->auth_type,
+ s->credentials, DCERPC_AUTH_TYPE_SPNEGO,
dcerpc_auth_level(s->pipe->conn),
s->table->authservices->names[0]);
if (composite_nomem(auth_req, c)) return;
- composite_continue(c, auth_req, continue_recv_bind, c);
+ composite_continue(c, auth_req, continue_auth, c);
}
/*
Stage 2 of pipe_auth: Receive result of non-authenticated bind request
*/
-static void continue_auth_recv_none(struct composite_context *ctx)
+static void continue_auth_none(struct composite_context *ctx)
{
struct composite_context *c = talloc_get_type(ctx->async.private_data,
struct composite_context);
@@ -1158,6 +1199,8 @@ struct composite_context *dcerpc_pipe_auth_send(struct dcerpc_pipe *p,
* connection is not signed or sealed. For that case
* we rely on the already authenticated CIFS connection
*/
+
+ uint8_t auth_type;
if ((conn->flags & (DCERPC_SIGN|DCERPC_SEAL)) == 0) {
/*
@@ -1171,34 +1214,40 @@ struct composite_context *dcerpc_pipe_auth_send(struct dcerpc_pipe *p,
}
if (s->binding->flags & DCERPC_AUTH_SPNEGO) {
- s->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
+ auth_type = DCERPC_AUTH_TYPE_SPNEGO;
} else if (s->binding->flags & DCERPC_AUTH_KRB5) {
- s->auth_type = DCERPC_AUTH_TYPE_KRB5;
+ auth_type = DCERPC_AUTH_TYPE_KRB5;
} else if (s->binding->flags & DCERPC_SCHANNEL) {
- s->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
+ auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
} else if (s->binding->flags & DCERPC_AUTH_NTLM) {
- s->auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
+ auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
} else {
- s->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
- s->try_ntlm_fallback = True;
+ auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table,
+ s->credentials, DCERPC_AUTH_TYPE_SPNEGO,
+ dcerpc_auth_level(conn),
+ s->table->authservices->names[0]);
+ if (composite_nomem(auth_req, c)) return c;
+
+ composite_continue(c, auth_req, continue_auth_auto, c);
+ return c;
}
-
+
auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table,
- s->credentials, s->auth_type,
+ s->credentials, auth_type,
dcerpc_auth_level(conn),
s->table->authservices->names[0]);
if (composite_nomem(auth_req, c)) return c;
- composite_continue(c, auth_req, continue_recv_bind, c);
+ composite_continue(c, auth_req, continue_auth, c);
} else {
auth_none_req = dcerpc_bind_auth_none_send(c, s->pipe, s->table);
if (composite_nomem(auth_none_req, c)) return c;
- composite_continue(c, auth_none_req, continue_auth_recv_none, c);
+ composite_continue(c, auth_none_req, continue_auth_none, c);
}
return c;
@@ -1212,7 +1261,7 @@ struct composite_context *dcerpc_pipe_auth_send(struct dcerpc_pipe *p,
supllied, as it rebinds to a new pipe due to authentication fallback
*/
-NTSTATUS dcerpc_pipe_auth_recv(struct composite_context *c,
+NTSTATUS dcerpc_pipe_auth_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
struct dcerpc_pipe **p)
{
NTSTATUS status;
@@ -1225,6 +1274,7 @@ NTSTATUS dcerpc_pipe_auth_recv(struct composite_context *c,
DEBUG(0, ("Failed to bind to uuid %s - %s\n", uuid_str, nt_errstr(status)));
talloc_free(uuid_str);
} else {
+ talloc_steal(mem_ctx, s->pipe);
*p = s->pipe;
}
@@ -1238,7 +1288,8 @@ NTSTATUS dcerpc_pipe_auth_recv(struct composite_context *c,
This may change *p, as it rebinds to a new pipe due to authentication fallback
*/
-NTSTATUS dcerpc_pipe_auth(struct dcerpc_pipe **p,
+NTSTATUS dcerpc_pipe_auth(TALLOC_CTX *mem_ctx,
+ struct dcerpc_pipe **p,
struct dcerpc_binding *binding,
const struct dcerpc_interface_table *table,
struct cli_credentials *credentials)
@@ -1246,7 +1297,7 @@ NTSTATUS dcerpc_pipe_auth(struct dcerpc_pipe **p,
struct composite_context *c;
c = dcerpc_pipe_auth_send(*p, binding, table, credentials);
- return dcerpc_pipe_auth_recv(c, p);
+ return dcerpc_pipe_auth_recv(c, mem_ctx, p);
}