diff --git a/libcli/smb/smb2cli_tcon.c b/libcli/smb/smb2cli_tcon.c
index 8863bae0764..7bbae8ea3b3 100644
--- a/libcli/smb/smb2cli_tcon.c
+++ b/libcli/smb/smb2cli_tcon.c
@@ -23,42 +23,38 @@
 #include "../libcli/smb/smb_common.h"
 #include "../libcli/smb/smbXcli_base.h"
 
-struct smb2cli_tcon_state {
-	struct tevent_context *ev;
-	struct smbXcli_conn *conn;
-	uint32_t timeout_msec;
+struct smb2cli_raw_tcon_state {
 	struct smbXcli_session *session;
 	struct smbXcli_tcon *tcon;
 	uint8_t fixed[8];
 	uint8_t dyn_pad[1];
 };
 
-static void smb2cli_tcon_done(struct tevent_req *subreq);
+static void smb2cli_raw_tcon_done(struct tevent_req *subreq);
 
-struct tevent_req *smb2cli_tcon_send(TALLOC_CTX *mem_ctx,
-				     struct tevent_context *ev,
-				     struct smbXcli_conn *conn,
-				     uint32_t timeout_msec,
-				     struct smbXcli_session *session,
-				     struct smbXcli_tcon *tcon,
-				     uint16_t flags,
-				     const char *unc)
+struct tevent_req *smb2cli_raw_tcon_send(TALLOC_CTX *mem_ctx,
+					 struct tevent_context *ev,
+					 struct smbXcli_conn *conn,
+					 uint32_t additional_flags,
+					 uint32_t clear_flags,
+					 uint32_t timeout_msec,
+					 struct smbXcli_session *session,
+					 struct smbXcli_tcon *tcon,
+					 uint16_t tcon_flags,
+					 const char *unc)
 {
-	struct tevent_req *req, *subreq;
-	struct smb2cli_tcon_state *state;
-	uint8_t *fixed;
-	uint8_t *dyn;
+	struct tevent_req *req = NULL;
+	struct smb2cli_raw_tcon_state *state = NULL;
+	struct tevent_req *subreq = NULL;
+	uint8_t *fixed = NULL;
+	uint8_t *dyn = NULL;
 	size_t dyn_len;
-	uint32_t additional_flags = 0;
-	uint32_t clear_flags = 0;
 
-	req = tevent_req_create(mem_ctx, &state, struct smb2cli_tcon_state);
+	req = tevent_req_create(mem_ctx, &state,
+				struct smb2cli_raw_tcon_state);
 	if (req == NULL) {
 		return NULL;
 	}
-	state->ev = ev;
-	state->conn = conn;
-	state->timeout_msec = timeout_msec;
 	state->session = session;
 	state->tcon = tcon;
 
@@ -77,7 +73,7 @@ struct tevent_req *smb2cli_tcon_send(TALLOC_CTX *mem_ctx,
 	fixed = state->fixed;
 	SSVAL(fixed, 0, 9);
 	if (smbXcli_conn_protocol(conn) >= PROTOCOL_SMB3_10) {
-		SSVAL(fixed, 2, flags);
+		SSVAL(fixed, 2, tcon_flags);
 	} else {
 		SSVAL(fixed, 2, 0); /* Reserved */
 	}
@@ -89,10 +85,6 @@ struct tevent_req *smb2cli_tcon_send(TALLOC_CTX *mem_ctx,
 		dyn_len = sizeof(state->dyn_pad);
 	}
 
-	if (smbXcli_session_is_authenticated(state->session)) {
-		additional_flags |= SMB2_HDR_FLAG_SIGNED;
-	}
-
 	subreq = smb2cli_req_send(state, ev, conn, SMB2_OP_TCON,
 				  additional_flags, clear_flags,
 				  timeout_msec,
@@ -104,19 +96,17 @@ struct tevent_req *smb2cli_tcon_send(TALLOC_CTX *mem_ctx,
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
-	tevent_req_set_callback(subreq, smb2cli_tcon_done, req);
+	tevent_req_set_callback(subreq, smb2cli_raw_tcon_done, req);
 
 	return req;
 }
 
-static void smb2cli_tcon_validate(struct tevent_req *subreq);
-
-static void smb2cli_tcon_done(struct tevent_req *subreq)
+static void smb2cli_raw_tcon_done(struct tevent_req *subreq)
 {
 	struct tevent_req *req = tevent_req_callback_data(
 		subreq, struct tevent_req);
-	struct smb2cli_tcon_state *state = tevent_req_data(
-		req, struct smb2cli_tcon_state);
+	struct smb2cli_raw_tcon_state *state = tevent_req_data(
+		req, struct smb2cli_raw_tcon_state);
 	NTSTATUS status;
 	struct iovec *iov;
 	uint8_t *body;
@@ -156,6 +146,129 @@ static void smb2cli_tcon_done(struct tevent_req *subreq)
 				share_capabilities,
 				maximal_access);
 
+	tevent_req_done(req);
+}
+
+NTSTATUS smb2cli_raw_tcon_recv(struct tevent_req *req)
+{
+	return tevent_req_simple_recv_ntstatus(req);
+}
+
+NTSTATUS smb2cli_raw_tcon(struct smbXcli_conn *conn,
+			  uint32_t additional_flags,
+			  uint32_t clear_flags,
+			  uint32_t timeout_msec,
+			  struct smbXcli_session *session,
+			  struct smbXcli_tcon *tcon,
+			  uint16_t tcon_flags,
+			  const char *unc)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+	struct tevent_context *ev;
+	struct tevent_req *req;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+	if (smbXcli_conn_has_async_calls(conn)) {
+		/*
+		 * Can't use sync call while an async call is in flight
+		 */
+		status = NT_STATUS_INVALID_PARAMETER;
+		goto fail;
+	}
+	ev = samba_tevent_context_init(frame);
+	if (ev == NULL) {
+		goto fail;
+	}
+	req = smb2cli_raw_tcon_send(frame, ev, conn,
+				    additional_flags, clear_flags,
+				    timeout_msec, session, tcon,
+				    tcon_flags, unc);
+	if (req == NULL) {
+		goto fail;
+	}
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+		goto fail;
+	}
+	status = smb2cli_raw_tcon_recv(req);
+ fail:
+	TALLOC_FREE(frame);
+	return status;
+}
+
+struct smb2cli_tcon_state {
+	struct tevent_context *ev;
+	struct smbXcli_conn *conn;
+	uint32_t timeout_msec;
+	struct smbXcli_session *session;
+	struct smbXcli_tcon *tcon;
+	uint8_t fixed[8];
+	uint8_t dyn_pad[1];
+};
+
+static void smb2cli_tcon_done(struct tevent_req *subreq);
+
+struct tevent_req *smb2cli_tcon_send(TALLOC_CTX *mem_ctx,
+				     struct tevent_context *ev,
+				     struct smbXcli_conn *conn,
+				     uint32_t timeout_msec,
+				     struct smbXcli_session *session,
+				     struct smbXcli_tcon *tcon,
+				     uint16_t flags,
+				     const char *unc)
+{
+	struct tevent_req *req, *subreq;
+	struct smb2cli_tcon_state *state;
+	uint32_t additional_flags = 0;
+	uint32_t clear_flags = 0;
+
+	req = tevent_req_create(mem_ctx, &state, struct smb2cli_tcon_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->ev = ev;
+	state->conn = conn;
+	state->timeout_msec = timeout_msec;
+	state->session = session;
+	state->tcon = tcon;
+
+	if (smbXcli_session_is_authenticated(state->session)) {
+		additional_flags |= SMB2_HDR_FLAG_SIGNED;
+	}
+
+	subreq = smb2cli_raw_tcon_send(state,
+				       state->ev,
+				       state->conn,
+				       additional_flags,
+				       clear_flags,
+				       state->timeout_msec,
+				       state->session,
+				       state->tcon,
+				       flags,
+				       unc);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, smb2cli_tcon_done, req);
+
+	return req;
+}
+
+static void smb2cli_tcon_validate(struct tevent_req *subreq);
+
+static void smb2cli_tcon_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct smb2cli_tcon_state *state = tevent_req_data(
+		req, struct smb2cli_tcon_state);
+	NTSTATUS status;
+
+	status = smb2cli_raw_tcon_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
 	if (!smbXcli_session_is_authenticated(state->session)) {
 		tevent_req_done(req);
 		return;
diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h
index ac382b2ae6a..75e758f5a84 100644
--- a/libcli/smb/smbXcli_base.h
+++ b/libcli/smb/smbXcli_base.h
@@ -589,6 +589,26 @@ NTSTATUS smb2cli_logoff(struct smbXcli_conn *conn,
 			uint32_t timeout_msec,
 			struct smbXcli_session *session);
 
+/* smb2cli_raw_tcon* should only be used in tests! */
+struct tevent_req *smb2cli_raw_tcon_send(TALLOC_CTX *mem_ctx,
+					 struct tevent_context *ev,
+					 struct smbXcli_conn *conn,
+					 uint32_t additional_flags,
+					 uint32_t clear_flags,
+					 uint32_t timeout_msec,
+					 struct smbXcli_session *session,
+					 struct smbXcli_tcon *tcon,
+					 uint16_t tcon_flags,
+					 const char *unc);
+NTSTATUS smb2cli_raw_tcon_recv(struct tevent_req *req);
+NTSTATUS smb2cli_raw_tcon(struct smbXcli_conn *conn,
+			  uint32_t additional_flags,
+			  uint32_t clear_flags,
+			  uint32_t timeout_msec,
+			  struct smbXcli_session *session,
+			  struct smbXcli_tcon *tcon,
+			  uint16_t tcon_flags,
+			  const char *unc);
 struct tevent_req *smb2cli_tcon_send(TALLOC_CTX *mem_ctx,
 				     struct tevent_context *ev,
 				     struct smbXcli_conn *conn,