diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c index 1ec11a9..8b91019 100644 --- a/libcli/smb/smbXcli_base.c +++ b/libcli/smb/smbXcli_base.c @@ -6099,6 +6099,34 @@ struct smbXcli_tcon *smbXcli_tcon_create(TALLOC_CTX *mem_ctx) return tcon; } +struct smbXcli_tcon *smbXcli_tcon_copy(TALLOC_CTX *mem_ctx, + const struct smbXcli_tcon *tcon_in) +{ + struct smbXcli_tcon *tcon; + + tcon = talloc_memdup(mem_ctx, tcon_in, sizeof(struct smbXcli_tcon)); + if (tcon == NULL) { + return NULL; + } + + /* Deal with the SMB1 strings. */ + if (tcon_in->smb1.service != NULL) { + tcon->smb1.service = talloc_strdup(tcon, tcon_in->smb1.service); + if (tcon->smb1.service == NULL) { + TALLOC_FREE(tcon); + return NULL; + } + } + if (tcon->smb1.fs_type != NULL) { + tcon->smb1.fs_type = talloc_strdup(tcon, tcon_in->smb1.fs_type); + if (tcon->smb1.fs_type == NULL) { + TALLOC_FREE(tcon); + return NULL; + } + } + return tcon; +} + void smbXcli_tcon_set_fs_attributes(struct smbXcli_tcon *tcon, uint32_t fs_attributes) { @@ -6177,6 +6205,11 @@ uint32_t smb2cli_tcon_current_id(struct smbXcli_tcon *tcon) return tcon->smb2.tcon_id; } +void smb2cli_tcon_set_id(struct smbXcli_tcon *tcon, uint32_t tcon_id) +{ + tcon->smb2.tcon_id = tcon_id; +} + uint32_t smb2cli_tcon_capabilities(struct smbXcli_tcon *tcon) { return tcon->smb2.capabilities; diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h index 1abeb2b..52fec9a 100644 --- a/libcli/smb/smbXcli_base.h +++ b/libcli/smb/smbXcli_base.h @@ -501,6 +501,8 @@ NTSTATUS smb2cli_session_set_channel_key(struct smbXcli_session *session, NTSTATUS smb2cli_session_encryption_on(struct smbXcli_session *session); struct smbXcli_tcon *smbXcli_tcon_create(TALLOC_CTX *mem_ctx); +struct smbXcli_tcon *smbXcli_tcon_copy(TALLOC_CTX *mem_ctx, + const struct smbXcli_tcon *tcon_in); void smbXcli_tcon_set_fs_attributes(struct smbXcli_tcon *tcon, uint32_t fs_attributes); uint32_t smbXcli_tcon_get_fs_attributes(struct smbXcli_tcon *tcon); @@ -515,6 +517,7 @@ bool smb1cli_tcon_set_values(struct smbXcli_tcon *tcon, const char *service, const char *fs_type); uint32_t smb2cli_tcon_current_id(struct smbXcli_tcon *tcon); +void smb2cli_tcon_set_id(struct smbXcli_tcon *tcon, uint32_t tcon_id); uint32_t smb2cli_tcon_capabilities(struct smbXcli_tcon *tcon); uint32_t smb2cli_tcon_flags(struct smbXcli_tcon *tcon); void smb2cli_tcon_set_values(struct smbXcli_tcon *tcon, diff --git a/source3/client/client.c b/source3/client/client.c index 6464736..3285240 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -4712,7 +4712,10 @@ static int cmd_tid(void) d_printf("no tcon currently\n"); } } else { - uint16_t tid = atoi(tid_str); + uint32_t tid = atoi(tid_str); + if (!cli_state_has_tcon(cli)) { + d_printf("no tcon currently\n"); + } cli_state_set_tid(cli, tid); } diff --git a/source3/lib/util_sd.c b/source3/lib/util_sd.c index d79fe79..ee4f6c6 100644 --- a/source3/lib/util_sd.c +++ b/source3/lib/util_sd.c @@ -84,7 +84,7 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli, enum lsa_SidType *type, char **domain, char **name) { - uint16_t orig_cnum = cli_state_get_tid(cli); + void *orig_tcon = NULL; struct rpc_pipe_client *p = NULL; struct policy_handle handle; NTSTATUS status; @@ -93,6 +93,14 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli, char **domains; char **names; + if (cli_state_has_tcon(cli)) { + orig_tcon = cli_state_save_tcon(cli); + if (orig_tcon == NULL) { + status = NT_STATUS_NO_MEMORY; + goto tcon_fail; + } + } + status = cli_tree_connect(cli, "IPC$", "?????", NULL); if (!NT_STATUS_IS_OK(status)) { goto tcon_fail; @@ -125,7 +133,7 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli, TALLOC_FREE(p); cli_tdis(cli); tcon_fail: - cli_state_set_tid(cli, orig_cnum); + cli_state_restore_tcon(cli, orig_tcon); TALLOC_FREE(frame); return status; } @@ -165,7 +173,7 @@ static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli, enum lsa_SidType *type, struct dom_sid *sid) { - uint16_t orig_cnum = cli_state_get_tid(cli); + void *orig_tcon = NULL; struct rpc_pipe_client *p; struct policy_handle handle; NTSTATUS status; @@ -173,6 +181,14 @@ static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli, struct dom_sid *sids; enum lsa_SidType *types; + if (cli_state_has_tcon(cli)) { + orig_tcon = cli_state_save_tcon(cli); + if (orig_tcon == NULL) { + status = NT_STATUS_NO_MEMORY; + goto tcon_fail; + } + } + status = cli_tree_connect(cli, "IPC$", "?????", NULL); if (!NT_STATUS_IS_OK(status)) { goto tcon_fail; @@ -204,7 +220,7 @@ static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli, TALLOC_FREE(p); cli_tdis(cli); tcon_fail: - cli_state_set_tid(cli, orig_cnum); + cli_state_restore_tcon(cli, orig_tcon); TALLOC_FREE(frame); return status; } diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 200657a..6e86352 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1948,6 +1948,13 @@ struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx, state->cli = cli; vwv = state->vwv; + TALLOC_FREE(cli->smb1.tcon); + cli->smb1.tcon = smbXcli_tcon_create(cli); + if (tevent_req_nomem(cli->smb1.tcon, req)) { + return tevent_req_post(req, ev); + } + smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX); + cli->share = talloc_strdup(cli, share); if (!cli->share) { return NULL; @@ -2257,6 +2264,7 @@ static struct tevent_req *cli_tree_connect_send( if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { char *unc; + TALLOC_FREE(cli->smb2.tcon); cli->smb2.tcon = smbXcli_tcon_create(cli); if (tevent_req_nomem(cli->smb2.tcon, req)) { return tevent_req_post(req, ev); @@ -2430,6 +2438,7 @@ static void cli_tdis_done(struct tevent_req *subreq) return; } cli_state_set_tid(state->cli, UINT16_MAX); + TALLOC_FREE(state->cli->smb1.tcon); tevent_req_done(req); } @@ -2445,10 +2454,14 @@ NTSTATUS cli_tdis(struct cli_state *cli) NTSTATUS status = NT_STATUS_NO_MEMORY; if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { - return smb2cli_tdis(cli->conn, + status = smb2cli_tdis(cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon); + if (NT_STATUS_IS_OK(status)) { + TALLOC_FREE(cli->smb2.tcon); + } + return status; } if (smbXcli_conn_has_async_calls(cli->conn)) { @@ -3617,12 +3630,20 @@ static struct tevent_req *cli_raw_tcon_send( } if (!lp_client_plaintext_auth() && (*pass)) { - DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'" - " or 'client ntlmv2 auth = yes'\n")); + DEBUG(1, ("Server requested PLAINTEXT %d %s password but 'client plaintext auth = no'" + " or 'client ntlmv2 auth = yes'\n", + (int)lp_client_plaintext_auth(), pass)); tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); return tevent_req_post(req, ev); } + TALLOC_FREE(cli->smb1.tcon); + cli->smb1.tcon = smbXcli_tcon_create(cli); + if (tevent_req_nomem(cli->smb1.tcon, req)) { + return tevent_req_post(req, ev); + } + smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX); + bytes = talloc_array(state, uint8_t, 0); bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0); bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index c477d7c..ff65879 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -1205,7 +1205,7 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, size_t consumed = 0; char *fullpath = NULL; bool res; - uint16_t cnum; + void *orig_tcon = NULL; char *newextrapath = NULL; NTSTATUS status; const char *remote_name; @@ -1215,7 +1215,6 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, } remote_name = smbXcli_conn_remote_name(cli->conn); - cnum = cli_state_get_tid(cli); /* special case. never check for a referral on the IPC$ share */ @@ -1230,15 +1229,25 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, return false; } + /* Store tcon state. */ + if (cli_state_has_tcon(cli)) { + orig_tcon = cli_state_save_tcon(cli); + if (orig_tcon == NULL) { + return false; + } + } + /* check for the referral */ if (!NT_STATUS_IS_OK(cli_tree_connect(cli, "IPC$", "IPC", NULL))) { + cli_state_restore_tcon(cli, orig_tcon); return false; } if (force_encrypt) { status = cli_cm_force_encryption_creds(cli, creds, "IPC$"); if (!NT_STATUS_IS_OK(status)) { + cli_state_restore_tcon(cli, orig_tcon); return false; } } @@ -1248,12 +1257,13 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, res = NT_STATUS_IS_OK(status); status = cli_tdis(cli); + + cli_state_restore_tcon(cli, orig_tcon); + if (!NT_STATUS_IS_OK(status)) { return false; } - cli_state_set_tid(cli, cnum); - if (!res || !num_refs) { return false; } diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index bc5c1b1..e10fb32 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -227,11 +227,6 @@ struct cli_state *cli_state_create(TALLOC_CTX *mem_ctx, cli->smb1.pid = (uint32_t)getpid(); cli->smb1.vc_num = cli->smb1.pid; - cli->smb1.tcon = smbXcli_tcon_create(cli); - if (cli->smb1.tcon == NULL) { - goto error; - } - smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX); cli->smb1.session = smbXcli_session_create(cli, cli->conn); if (cli->smb1.session == NULL) { goto error; @@ -341,27 +336,70 @@ uint32_t cli_getpid(struct cli_state *cli) bool cli_state_has_tcon(struct cli_state *cli) { - uint16_t tid = cli_state_get_tid(cli); - - if (tid == UINT16_MAX) { - return false; + uint32_t tid; + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + if (cli->smb2.tcon == NULL) { + return false; + } + tid = cli_state_get_tid(cli); + if (tid == UINT32_MAX) { + return false; + } + } else { + if (cli->smb1.tcon == NULL) { + return false; + } + tid = cli_state_get_tid(cli); + if (tid == UINT16_MAX) { + return false; + } } return true; } -uint16_t cli_state_get_tid(struct cli_state *cli) +uint32_t cli_state_get_tid(struct cli_state *cli) { - return smb1cli_tcon_current_id(cli->smb1.tcon); + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + return smb2cli_tcon_current_id(cli->smb2.tcon); + } else { + return smb1cli_tcon_current_id(cli->smb1.tcon); + } } -uint16_t cli_state_set_tid(struct cli_state *cli, uint16_t tid) +uint32_t cli_state_set_tid(struct cli_state *cli, uint32_t tid) { - uint16_t ret = smb1cli_tcon_current_id(cli->smb1.tcon); - smb1cli_tcon_set_id(cli->smb1.tcon, tid); + uint32_t ret; + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + ret = smb2cli_tcon_current_id(cli->smb2.tcon); + smb2cli_tcon_set_id(cli->smb1.tcon, tid); + } else { + ret = smb1cli_tcon_current_id(cli->smb1.tcon); + smb1cli_tcon_set_id(cli->smb1.tcon, tid); + } return ret; } +void *cli_state_save_tcon(struct cli_state *cli) +{ + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + return smbXcli_tcon_copy(cli, cli->smb2.tcon); + } else { + return smbXcli_tcon_copy(cli, cli->smb1.tcon); + } +} + +void cli_state_restore_tcon(struct cli_state *cli, void *tcon) +{ + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + TALLOC_FREE(cli->smb2.tcon); + cli->smb2.tcon = (struct smbXcli_tcon *)tcon; + } else { + TALLOC_FREE(cli->smb1.tcon); + cli->smb1.tcon = (struct smbXcli_tcon *)tcon; + } +} + uint16_t cli_state_get_uid(struct cli_state *cli) { return smb1cli_session_current_id(cli->smb1.session); diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h index 137c355..eb8bf8e 100644 --- a/source3/libsmb/proto.h +++ b/source3/libsmb/proto.h @@ -194,8 +194,10 @@ uint16_t cli_state_get_vc_num(struct cli_state *cli); uint32_t cli_setpid(struct cli_state *cli, uint32_t pid); uint32_t cli_getpid(struct cli_state *cli); bool cli_state_has_tcon(struct cli_state *cli); -uint16_t cli_state_get_tid(struct cli_state *cli); -uint16_t cli_state_set_tid(struct cli_state *cli, uint16_t tid); +uint32_t cli_state_get_tid(struct cli_state *cli); +uint32_t cli_state_set_tid(struct cli_state *cli, uint32_t tid); +void *cli_state_save_tcon(struct cli_state *cli); +void cli_state_restore_tcon(struct cli_state *cli, void *tcon); uint16_t cli_state_get_uid(struct cli_state *cli); uint16_t cli_state_set_uid(struct cli_state *cli, uint16_t uid); bool cli_set_case_sensitive(struct cli_state *cli, bool case_sensitive); diff --git a/source3/torture/test_smb2.c b/source3/torture/test_smb2.c index c0d11e6..e799977 100644 --- a/source3/torture/test_smb2.c +++ b/source3/torture/test_smb2.c @@ -43,7 +43,7 @@ bool run_smb2_basic(int dummy) uint8_t *dir_data; uint32_t dir_data_length; uint32_t saved_tid = 0; - struct smbXcli_tcon *saved_tcon = NULL; + void *saved_tcon = NULL; uint64_t saved_uid = 0; printf("Starting SMB2-BASIC\n"); @@ -170,7 +170,10 @@ bool run_smb2_basic(int dummy) } saved_tid = smb2cli_tcon_current_id(cli->smb2.tcon); - saved_tcon = cli->smb2.tcon; + saved_tcon = cli_state_save_tcon(cli); + if (saved_tcon == NULL) { + return false; + } cli->smb2.tcon = smbXcli_tcon_create(cli); smb2cli_tcon_set_values(cli->smb2.tcon, NULL, /* session */ @@ -187,8 +190,7 @@ bool run_smb2_basic(int dummy) printf("smb2cli_tdis returned %s\n", nt_errstr(status)); return false; } - talloc_free(cli->smb2.tcon); - cli->smb2.tcon = saved_tcon; + cli_state_restore_tcon(cli, saved_tcon); status = smb2cli_tdis(cli->conn, cli->timeout, diff --git a/source3/torture/torture.c b/source3/torture/torture.c index bdcf1e1..27544e8 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -1301,7 +1301,8 @@ static bool run_tcon_test(int dummy) static struct cli_state *cli; const char *fname = "\\tcontest.tmp"; uint16_t fnum1; - uint16_t cnum1, cnum2, cnum3; + uint32_t cnum1, cnum2, cnum3; + void *orig_tcon = NULL; uint16_t vuid1, vuid2; char buf[4]; bool ret = True; @@ -1333,6 +1334,8 @@ static bool run_tcon_test(int dummy) return False; } + orig_tcon = cli_state_save_tcon(cli); + status = cli_tree_connect_creds(cli, share, "?????", torture_creds); if (!NT_STATUS_IS_OK(status)) { printf("%s refused 2nd tree connect (%s)\n", host, @@ -1400,6 +1403,8 @@ static bool run_tcon_test(int dummy) return False; } + cli_state_restore_tcon(cli, orig_tcon); + cli_state_set_tid(cli, cnum1); if (!torture_close_connection(cli)) { @@ -2764,8 +2769,8 @@ static bool run_fdsesstest(int dummy) struct cli_state *cli; uint16_t new_vuid; uint16_t saved_vuid; - uint16_t new_cnum; - uint16_t saved_cnum; + uint32_t new_cnum; + uint32_t saved_cnum; const char *fname = "\\fdsess.tst"; const char *fname1 = "\\fdsess1.tst"; uint16_t fnum1; @@ -9015,8 +9020,9 @@ static bool run_uid_regression_test(int dummy) { static struct cli_state *cli; int16_t old_vuid; - int16_t old_cnum; + int32_t old_cnum; bool correct = True; + void *orig_tcon = NULL; NTSTATUS status; printf("starting uid regression test\n"); @@ -9057,6 +9063,7 @@ static bool run_uid_regression_test(int dummy) } old_cnum = cli_state_get_tid(cli); + orig_tcon = cli_state_save_tcon(cli); /* Now try a SMBtdis with the invald vuid set to zero. */ cli_state_set_uid(cli, 0); @@ -9069,9 +9076,11 @@ static bool run_uid_regression_test(int dummy) } else { d_printf("First tdis failed (%s)\n", nt_errstr(status)); correct = false; + cli_state_restore_tcon(cli, orig_tcon); goto out; } + cli_state_restore_tcon(cli, orig_tcon); cli_state_set_uid(cli, old_vuid); cli_state_set_tid(cli, old_cnum); diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index e98f65a..eb1d858 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -5101,7 +5101,7 @@ static void show_userlist(struct rpc_pipe_client *pipe_hnd, union srvsvc_NetShareInfo info; WERROR result; NTSTATUS status; - uint16_t cnum; + void *orig_tcon; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx, @@ -5123,9 +5123,15 @@ static void show_userlist(struct rpc_pipe_client *pipe_hnd, netname)); } - cnum = cli_state_get_tid(cli); + if (cli_state_has_tcon(cli)) { + orig_tcon = cli_state_save_tcon(cli); + if (orig_tcon == NULL) { + return; + } + } if (!NT_STATUS_IS_OK(cli_tree_connect(cli, netname, "A:", NULL))) { + cli_state_restore_tcon(cli, orig_tcon); return; } @@ -5168,7 +5174,7 @@ static void show_userlist(struct rpc_pipe_client *pipe_hnd, if (fnum != (uint16_t)-1) cli_close(cli, fnum); cli_tdis(cli); - cli_state_set_tid(cli, cnum); + cli_state_restore_tcon(cli, orig_tcon); return; } diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c index 11289e6..47ffda1 100644 --- a/source3/utils/smbcacls.c +++ b/source3/utils/smbcacls.c @@ -51,12 +51,20 @@ static NTSTATUS cli_lsa_lookup_domain_sid(struct cli_state *cli, struct dom_sid *sid) { union lsa_PolicyInformation *info = NULL; - uint16_t orig_cnum = cli_state_get_tid(cli); + void *orig_tcon = NULL; struct rpc_pipe_client *rpc_pipe = NULL; struct policy_handle handle; NTSTATUS status, result; TALLOC_CTX *frame = talloc_stackframe(); + if (cli_state_has_tcon(cli)) { + orig_tcon = cli_state_save_tcon(cli); + if (orig_tcon == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + } + status = cli_tree_connect(cli, "IPC$", "?????", NULL); if (!NT_STATUS_IS_OK(status)) { goto done; @@ -88,7 +96,7 @@ tdis: TALLOC_FREE(rpc_pipe); cli_tdis(cli); done: - cli_state_set_tid(cli, orig_cnum); + cli_state_restore_tcon(cli, orig_tcon); TALLOC_FREE(frame); return status; }