svn commit: samba r15500 - in branches/SAMBA_4_0/source: libnet librpc/rpc torture/rpc

abartlet at samba.org abartlet at samba.org
Sun May 7 18:11:48 GMT 2006


Author: abartlet
Date: 2006-05-07 18:11:47 +0000 (Sun, 07 May 2006)
New Revision: 15500

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=15500

Log:
Add support for interactive prompting on bad passwords to the RPC libraries.

This support requires that the bind_ack and alter_ack recv functions
also be send the DCE/RPC fault.  This would be best done by having the
ack run as a normal RPC reply callback, but this isn't easily possible
for now.

Andrew Bartlett

Modified:
   branches/SAMBA_4_0/source/libnet/libnet_join.c
   branches/SAMBA_4_0/source/librpc/rpc/dcerpc.c
   branches/SAMBA_4_0/source/librpc/rpc/dcerpc_connect.c
   branches/SAMBA_4_0/source/librpc/rpc/dcerpc_util.c
   branches/SAMBA_4_0/source/torture/rpc/bind.c


Changeset:
Modified: branches/SAMBA_4_0/source/libnet/libnet_join.c
===================================================================
--- branches/SAMBA_4_0/source/libnet/libnet_join.c	2006-05-07 18:09:54 UTC (rev 15499)
+++ branches/SAMBA_4_0/source/libnet/libnet_join.c	2006-05-07 18:11:47 UTC (rev 15500)
@@ -482,7 +482,7 @@
 
 	samr_pipe = connect_with_info->out.dcerpc_pipe;
 
-	status = dcerpc_pipe_auth(tmp_ctx, &samr_pipe,
+	status = dcerpc_pipe_auth(&samr_pipe,
 				  connect_with_info->out.dcerpc_pipe->binding, 
 				  &dcerpc_table_samr, ctx->cred);
 	if (!NT_STATUS_IS_OK(status)) {

Modified: branches/SAMBA_4_0/source/librpc/rpc/dcerpc.c
===================================================================
--- branches/SAMBA_4_0/source/librpc/rpc/dcerpc.c	2006-05-07 18:09:54 UTC (rev 15499)
+++ branches/SAMBA_4_0/source/librpc/rpc/dcerpc.c	2006-05-07 18:11:47 UTC (rev 15500)
@@ -490,6 +490,20 @@
 }
 
 /*
+  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)
@@ -555,27 +569,19 @@
 		dcerpc_connection_dead(conn, status);
 	}
 
-	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;
+	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;
+	}
 
-	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;
-	}
+	/* assume its an ordinary request */
+	dcerpc_request_recv_data(conn, blob, &pkt);
 }
 
 
@@ -591,6 +597,13 @@
 	/* 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));
@@ -1528,6 +1541,13 @@
 	/* 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) {

Modified: branches/SAMBA_4_0/source/librpc/rpc/dcerpc_connect.c
===================================================================
--- branches/SAMBA_4_0/source/librpc/rpc/dcerpc_connect.c	2006-05-07 18:09:54 UTC (rev 15499)
+++ branches/SAMBA_4_0/source/librpc/rpc/dcerpc_connect.c	2006-05-07 18:11:47 UTC (rev 15500)
@@ -764,7 +764,7 @@
 						      struct composite_context);
 	struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state);
 
-	c->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe);
+	c->status = dcerpc_pipe_auth_recv(s, &s->pipe);
 	if (!composite_is_ok(c)) return;
 
 	composite_done(c);
@@ -1170,7 +1170,8 @@
 	s = talloc_get_type(c->private_data, struct sec_conn_state);
 
 	if (NT_STATUS_IS_OK(status)) {
-		*p2 = talloc_steal(s->pipe, s->pipe2);
+		talloc_steal(s->pipe, s->pipe2);
+		*p2 = s->pipe2;
 	}
 
 	talloc_free(c);

Modified: branches/SAMBA_4_0/source/librpc/rpc/dcerpc_util.c
===================================================================
--- branches/SAMBA_4_0/source/librpc/rpc/dcerpc_util.c	2006-05-07 18:09:54 UTC (rev 15499)
+++ branches/SAMBA_4_0/source/librpc/rpc/dcerpc_util.c	2006-05-07 18:11:47 UTC (rev 15500)
@@ -976,14 +976,12 @@
 	struct dcerpc_binding *binding;
 	const struct dcerpc_interface_table *table;
 	struct cli_credentials *credentials;
+	uint8_t next_auth_type;
+	BOOL try_ntlm_fallback;
 };
 
 
-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);
+static void continue_new_auth_bind(struct composite_context *ctx);
 
 
 /*
@@ -1002,52 +1000,44 @@
 
 
 /*
-  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_auth_auto(struct composite_context *ctx)
+static void continue_recv_bind(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);
 
-	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);
+	status = dcerpc_bind_auth_recv(ctx);
+	if (s->try_ntlm_fallback && NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
 		struct composite_context *sec_conn_req;
-
+		s->try_ntlm_fallback = False;
+		s->next_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_ntlmssp_connection, c);
+		composite_continue(c, sec_conn_req, continue_new_auth_bind, c);
 		
 		return;
-	} 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);
+	} else if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
 		struct composite_context *sec_conn_req;
 		if (cli_credentials_wrong_password(s->credentials)) {
+			s->next_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
 			/* 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_spnego_after_wrong_pass, c);
+			composite_continue(c, sec_conn_req, continue_new_auth_bind, c);
+
+			return;
 		}
 	}
+	c->status = status;
 
 	if (!composite_is_ok(c)) return;
 	
@@ -1055,44 +1045,14 @@
 }
 
 /*
-  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;
+  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
 
-	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;
-
-	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
+  Calls back to stage 2 to process the response.
 */
-static void continue_spnego_after_wrong_pass(struct composite_context *ctx)
+static void continue_new_auth_bind(struct composite_context *ctx)
 {
 	struct composite_context *c;
 	struct pipe_auth_state *s;
@@ -1104,27 +1064,25 @@
 
 	/* 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, DCERPC_AUTH_TYPE_SPNEGO,
+					 s->credentials, s->next_auth_type,
 					 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);
+	composite_continue(c, auth_req, continue_recv_bind, c);
 }
 
 
 /*
   Stage 2 of pipe_auth: Receive result of non-authenticated bind request
 */
-static void continue_auth_none(struct composite_context *ctx)
+static void continue_auth_recv_none(struct composite_context *ctx)
 {
 	struct composite_context *c = talloc_get_type(ctx->async.private_data,
 						      struct composite_context);
@@ -1225,29 +1183,23 @@
 		} else if (s->binding->flags & DCERPC_AUTH_NTLM) {
 			auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
 		} else {
-			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_type = DCERPC_AUTH_TYPE_SPNEGO;
+			s->try_ntlm_fallback = True;
 		}
-		
+
 		auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table,
-						 s->credentials, auth_type,
+						 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, c);
+		composite_continue(c, auth_req, continue_recv_bind, 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_none, c);
+		composite_continue(c, auth_none_req, continue_auth_recv_none, c);
 	}
 
 	return c;
@@ -1261,7 +1213,7 @@
   supllied, as it rebinds to a new pipe due to authentication fallback
 
 */
-NTSTATUS dcerpc_pipe_auth_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, 
+NTSTATUS dcerpc_pipe_auth_recv(struct composite_context *c, 
 			       struct dcerpc_pipe **p)
 {
 	NTSTATUS status;
@@ -1274,7 +1226,6 @@
 		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;
 	}
 
@@ -1288,8 +1239,7 @@
 
    This may change *p, as it rebinds to a new pipe due to authentication fallback
 */
-NTSTATUS dcerpc_pipe_auth(TALLOC_CTX *mem_ctx,
-			  struct dcerpc_pipe **p, 
+NTSTATUS dcerpc_pipe_auth(struct dcerpc_pipe **p, 
 			  struct dcerpc_binding *binding,
 			  const struct dcerpc_interface_table *table,
 			  struct cli_credentials *credentials)
@@ -1297,7 +1247,7 @@
 	struct composite_context *c;
 
 	c = dcerpc_pipe_auth_send(*p, binding, table, credentials);
-	return dcerpc_pipe_auth_recv(c, mem_ctx, p);
+	return dcerpc_pipe_auth_recv(c, p);
 }
 
 

Modified: branches/SAMBA_4_0/source/torture/rpc/bind.c
===================================================================
--- branches/SAMBA_4_0/source/torture/rpc/bind.c	2006-05-07 18:09:54 UTC (rev 15499)
+++ branches/SAMBA_4_0/source/torture/rpc/bind.c	2006-05-07 18:11:47 UTC (rev 15500)
@@ -63,7 +63,7 @@
 		return False;
 	}
 
-	status = dcerpc_pipe_auth(mem_ctx, &p, binding, &dcerpc_table_lsarpc, cmdline_credentials);
+	status = dcerpc_pipe_auth(&p, binding, &dcerpc_table_lsarpc, cmdline_credentials);
 
 	if (NT_STATUS_IS_OK(status)) {
 		printf("(incorrectly) allowed re-bind to uuid %s - %s\n", 



More information about the samba-cvs mailing list