r15504: Revert -r 15500 and -r 15503 until I'm awake, and can get my head
authorAndrew Bartlett <abartlet@samba.org>
Sun, 7 May 2006 19:55:14 +0000 (19:55 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:05:43 +0000 (14:05 -0500)
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)

source4/libnet/libnet_join.c
source4/librpc/rpc/dcerpc.c
source4/librpc/rpc/dcerpc_connect.c
source4/librpc/rpc/dcerpc_util.c
source4/torture/rpc/bind.c

index 608568bc53e642b1dc417463664e18d612ec2e52..fb28eaed2f3c37f2fabad40d2685ca16c4e92d1a 100644 (file)
@@ -482,7 +482,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
 
        samr_pipe = connect_with_info->out.dcerpc_pipe;
 
-       status = dcerpc_pipe_auth(&samr_pipe,
+       status = dcerpc_pipe_auth(tmp_ctx, &samr_pipe,
                                  connect_with_info->out.dcerpc_pipe->binding, 
                                  &dcerpc_table_samr, ctx->cred);
        if (!NT_STATUS_IS_OK(status)) {
index adf67a7ba1c5c4cebd3fffa4d4b4d0c5dce32585..cd33d3d14b1c16a4901b44060f19522fde69925a 100644 (file)
@@ -489,20 +489,6 @@ static NTSTATUS dcerpc_map_reason(uint16_t reason)
        return NT_STATUS_UNSUCCESSFUL;
 }
 
-/*
-  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
 */
@@ -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) {
index 66b0af178bceb93a9aea7b1ee1f2e1d73e55bbb0..d69db51eb46b2e493eabadd5ba3695427b64a1f7 100644 (file)
@@ -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);
index 5b341b93595f66523e73a82cd4858199af4699f5..6c8ed7ecd8abd04f8d54c780c51c39e1321d0085 100644 (file)
@@ -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);
 
 
 /*
@@ -999,33 +1001,43 @@ 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);
 }
 
 
index 9467ad3d38e3c6b522ee870973ee2c2a2958de37..17580737f88b2acec9934f2c1e1318d08cfd9344 100644 (file)
@@ -63,7 +63,7 @@ BOOL torture_multi_bind(struct torture_context *torture)
                return False;
        }
 
-       status = dcerpc_pipe_auth(&p, binding, &dcerpc_table_lsarpc, cmdline_credentials);
+       status = dcerpc_pipe_auth(mem_ctx, &p, binding, &dcerpc_table_lsarpc, cmdline_credentials);
 
        if (NT_STATUS_IS_OK(status)) {
                printf("(incorrectly) allowed re-bind to uuid %s - %s\n",