From 463b308f16733b5a0bd896c46347d39064cee170 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 27 Mar 2012 11:09:05 +0200 Subject: [PATCH] s3:smbd: make use of smbXsrv_tcon and smbXsrv_session for smb2 The removes the protocol specific smbd_smb2_session and smbd_smb2_tcon. Pair-Programmed-With: Michael Adam metze --- source3/include/vfs.h | 1 + source3/librpc/idl/smbXsrv.idl | 1 - source3/smbd/conn_idle.c | 41 ++++------ source3/smbd/files.c | 8 +- source3/smbd/globals.h | 40 +--------- source3/smbd/password.c | 1 + source3/smbd/proto.h | 5 +- source3/smbd/service.c | 10 ++- source3/smbd/smb2_close.c | 2 +- source3/smbd/smb2_create.c | 4 +- source3/smbd/smb2_find.c | 2 +- source3/smbd/smb2_getinfo.c | 2 +- source3/smbd/smb2_glue.c | 6 +- source3/smbd/smb2_notify.c | 2 +- source3/smbd/smb2_read.c | 2 +- source3/smbd/smb2_server.c | 48 ++++++----- source3/smbd/smb2_sesssetup.c | 176 +++++++++++++++-------------------------- source3/smbd/smb2_setinfo.c | 2 +- source3/smbd/smb2_tcon.c | 100 +++++++++++------------ source3/smbd/smb2_write.c | 2 +- 20 files changed, 180 insertions(+), 275 deletions(-) diff --git a/source3/include/vfs.h b/source3/include/vfs.h index e6a9ef4541d..1496164fafe 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -280,6 +280,7 @@ struct share_params { typedef struct connection_struct { struct connection_struct *next, *prev; struct smbd_server_connection *sconn; /* can be NULL */ + struct smbXsrv_tcon0 *tcon; /* for now NULL for SMB1 */ uint32_t cnum; /* an index passed over the wire */ struct share_params *params; bool force_user; diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl index 44af7c83afa..215b72ebfbf 100644 --- a/source3/librpc/idl/smbXsrv.idl +++ b/source3/librpc/idl/smbXsrv.idl @@ -160,7 +160,6 @@ interface smbXsrv [ignore] gensec_security *gensec; [ignore] user_struct *compat; [ignore] smbXsrv_tcon_table *tcon_table; - [ignore] smbd_smb2_session *smb2sess; } smbXsrv_session0; typedef union { diff --git a/source3/smbd/conn_idle.c b/source3/smbd/conn_idle.c index 4dfa4097c31..22bc20ef1f5 100644 --- a/source3/smbd/conn_idle.c +++ b/source3/smbd/conn_idle.c @@ -88,19 +88,7 @@ bool conn_idle_all(struct smbd_server_connection *sconn, time_t t) void conn_close_all(struct smbd_server_connection *sconn) { if (sconn->using_smb2) { - /* SMB2 */ - struct smbd_smb2_session *sess; - - for (sess = sconn->smb2.sessions.list; sess; sess = sess->next) { - struct smbd_smb2_tcon *tcon, *tc_next; - - file_close_user(sconn, sess->vuid); - - for (tcon = sess->tcons.list; tcon; tcon = tc_next) { - tc_next = tcon->next; - TALLOC_FREE(tcon); - } - } + smbXsrv_session_logoff_all(sconn->conn); } else { /* SMB1 */ connection_struct *conn, *next; @@ -131,21 +119,20 @@ void conn_force_tdis(struct smbd_server_connection *sconn, const char *sharename } if (sconn->using_smb2) { - /* SMB2 */ - struct smbd_smb2_session *sess; - for (sess = sconn->smb2.sessions.list; sess; sess = sess->next) { - struct smbd_smb2_tcon *tcon, *tc_next; - - for (tcon = sess->tcons.list; tcon; tcon = tc_next) { - tc_next = tcon->next; - if (tcon->compat_conn && - strequal(lp_servicename(SNUM(tcon->compat_conn)), - sharename)) { - DEBUG(1,("Forcing close of share %s cnum=%d\n", - sharename, tcon->compat_conn->cnum)); - TALLOC_FREE(tcon); - } + for (conn=sconn->connections;conn;conn=next) { + struct smbXsrv_tcon *tcon; + + next = conn->next; + tcon = conn->tcon; + + if (!strequal(lp_servicename(SNUM(conn)), sharename)) { + continue; } + + DEBUG(1,("Forcing close of share %s cnum=%d\n", + sharename, conn->cnum)); + smbXsrv_tcon_disconnect(tcon, conn->vuid); + TALLOC_FREE(tcon); } } else { /* SMB1 */ diff --git a/source3/smbd/files.c b/source3/smbd/files.c index bec157b3da7..d11d6d764bd 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -680,7 +680,7 @@ struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req, return NULL; } - if (smb2req->tcon->compat_conn != fsp->conn) { + if (smb2req->tcon->compat != fsp->conn) { return NULL; } @@ -688,7 +688,11 @@ struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req, return NULL; } - if (smb2req->session->vuid != fsp->vuid) { + if (smb2req->session->compat == NULL) { + return NULL; + } + + if (smb2req->session->compat->vuid != fsp->vuid) { return NULL; } diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 9eadc99c0e2..a68c2034c8a 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -115,8 +115,6 @@ extern bool exit_firsttime; struct tstream_context; struct smbd_smb2_request; -struct smbd_smb2_session; -struct smbd_smb2_tcon; DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn); @@ -411,11 +409,11 @@ struct smbd_smb2_request { struct smbd_server_connection *sconn; /* the session the request operates on, maybe NULL */ - struct smbd_smb2_session *session; + struct smbXsrv_session *session; uint64_t last_session_id; /* the tcon the request operates on, maybe NULL */ - struct smbd_smb2_tcon *tcon; + struct smbXsrv_tcon *tcon; uint32_t last_tid; int current_idx; @@ -487,37 +485,6 @@ struct smbd_smb2_request { struct smbd_server_connection; struct user_struct; -struct smbd_smb2_session { - struct smbd_smb2_session *prev, *next; - struct smbd_server_connection *sconn; - NTSTATUS status; - uint64_t vuid; - struct gensec_security *gensec_security; - struct auth_session_info *session_info; - - struct smbXsrv_session *smbXsrv; - - struct user_struct *compat_vuser; - - struct { - /* an id tree used to allocate tids */ - struct idr_context *idtree; - - /* this is the limit of tid values for this connection */ - uint32_t limit; - - struct smbd_smb2_tcon *list; - } tcons; -}; - -struct smbd_smb2_tcon { - struct smbd_smb2_tcon *prev, *next; - struct smbd_smb2_session *session; - uint32_t tid; - int snum; - connection_struct *compat_conn; -}; - struct pending_message_list; struct pending_auth_data; @@ -674,9 +641,6 @@ struct smbd_server_connection { struct tstream_context *stream; bool negprot_2ff; struct { - struct smbd_smb2_session *list; - } sessions; - struct { /* The event that makes us process our blocking lock queue */ struct timed_event *brl_timeout; bool blocking_lock_unlock_state; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e8b48c464d8..b1ba66ac3fc 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -145,6 +145,7 @@ void invalidate_vuid(struct smbd_server_connection *sconn, uint64_t vuid) void invalidate_all_vuids(struct smbd_server_connection *sconn) { if (sconn->using_smb2) { + smbXsrv_session_logoff_all(sconn->conn); return; } diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 8196e696343..f774a3bf8cc 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -988,9 +988,10 @@ bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir); void load_registry_shares(void); int add_home_service(const char *service, const char *username, const char *homedir); int find_service(TALLOC_CTX *ctx, const char *service, char **p_service_out); -struct smbd_smb2_tcon; +struct smbXsrv_tcon0; connection_struct *make_connection_smb2(struct smbd_server_connection *sconn, - struct smbd_smb2_tcon *tcon, + struct smbXsrv_tcon0 *tcon, + int snum, struct user_struct *vuser, const char *pdev, NTSTATUS *pstatus); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 1bcbbcda6a3..fe5838225d9 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -941,7 +941,8 @@ static connection_struct *make_connection_smb1(struct smbd_server_connection *sc ****************************************************************************/ connection_struct *make_connection_smb2(struct smbd_server_connection *sconn, - struct smbd_smb2_tcon *tcon, + struct smbXsrv_tcon *tcon, + int snum, struct user_struct *vuser, const char *pdev, NTSTATUS *pstatus) @@ -952,10 +953,13 @@ connection_struct *make_connection_smb2(struct smbd_server_connection *sconn, *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } - conn->cnum = tcon->tid; + + conn->cnum = tcon->global->tcon_wire_id; + conn->tcon = tcon; + *pstatus = make_connection_snum(sconn, conn, - tcon->snum, + snum, vuser, pdev); if (!NT_STATUS_IS_OK(*pstatus)) { diff --git a/source3/smbd/smb2_close.c b/source3/smbd/smb2_close.c index a7f5df5ebba..566ac93ea25 100644 --- a/source3/smbd/smb2_close.c +++ b/source3/smbd/smb2_close.c @@ -158,7 +158,7 @@ static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req, { NTSTATUS status; struct smb_request *smbreq; - connection_struct *conn = req->tcon->compat_conn; + connection_struct *conn = req->tcon->compat; struct smb_filename *smb_fname = NULL; struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts; uint64_t allocation_size = 0; diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index 7dd7c5ca60e..f540377dcce 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -435,7 +435,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, ZERO_STRUCT(out_context_blobs); - if(lp_fake_oplocks(SNUM(smb2req->tcon->compat_conn))) { + if(lp_fake_oplocks(SNUM(smb2req->tcon->compat))) { requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE; } else { requested_oplock_level = in_oplock_level; @@ -783,7 +783,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, smb2req->compat_chain_fsp = smb1req->chain_fsp; - if(lp_fake_oplocks(SNUM(smb2req->tcon->compat_conn))) { + if(lp_fake_oplocks(SNUM(smb2req->tcon->compat))) { state->out_oplock_level = in_oplock_level; } else { state->out_oplock_level = map_samba_oplock_levels_to_smb2(result->oplock_type); diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c index 0464ad2c397..ef6887d3b7b 100644 --- a/source3/smbd/smb2_find.c +++ b/source3/smbd/smb2_find.c @@ -211,7 +211,7 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx, struct tevent_req *req; struct smbd_smb2_find_state *state; struct smb_request *smbreq; - connection_struct *conn = smb2req->tcon->compat_conn; + connection_struct *conn = smb2req->tcon->compat; NTSTATUS status; NTSTATUS empty_status; uint32_t info_level; diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index 10b093737fa..efd65a9daa9 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -253,7 +253,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, struct tevent_req *req; struct smbd_smb2_getinfo_state *state; struct smb_request *smbreq; - connection_struct *conn = smb2req->tcon->compat_conn; + connection_struct *conn = smb2req->tcon->compat; NTSTATUS status; req = tevent_req_create(mem_ctx, &state, diff --git a/source3/smbd/smb2_glue.c b/source3/smbd/smb2_glue.c index a71679fdf2f..d9d8f9a01c1 100644 --- a/source3/smbd/smb2_glue.c +++ b/source3/smbd/smb2_glue.c @@ -37,9 +37,9 @@ struct smb_request *smbd_smb2_fake_smb_request(struct smbd_smb2_request *req) } smbreq->request_time = req->request_time; - smbreq->vuid = req->session->compat_vuser->vuid; - smbreq->tid = req->tcon->compat_conn->cnum; - smbreq->conn = req->tcon->compat_conn; + smbreq->vuid = req->session->compat->vuid; + smbreq->tid = req->tcon->compat->cnum; + smbreq->conn = req->tcon->compat; smbreq->sconn = req->sconn; smbreq->smbpid = (uint16_t)IVAL(inhdr, SMB2_HDR_PID); smbreq->flags2 = FLAGS2_UNICODE_STRINGS | diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c index 20496c1c2c1..aa6d1906df6 100644 --- a/source3/smbd/smb2_notify.c +++ b/source3/smbd/smb2_notify.c @@ -195,7 +195,7 @@ static struct tevent_req *smbd_smb2_notify_send(TALLOC_CTX *mem_ctx, struct tevent_req *req; struct smbd_smb2_notify_state *state; struct smb_request *smbreq; - connection_struct *conn = smb2req->tcon->compat_conn; + connection_struct *conn = smb2req->tcon->compat; bool recursive = (in_flags & SMB2_WATCH_TREE) ? true : false; NTSTATUS status; diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c index 54bd3cdf7c0..0e08ff4a52f 100644 --- a/source3/smbd/smb2_read.c +++ b/source3/smbd/smb2_read.c @@ -389,7 +389,7 @@ static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx, struct tevent_req *req = NULL; struct smbd_smb2_read_state *state = NULL; struct smb_request *smbreq = NULL; - connection_struct *conn = smb2req->tcon->compat_conn; + connection_struct *conn = smb2req->tcon->compat; ssize_t nread = -1; struct lock_struct lock; int saved_errno; diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index f49c05cd568..a3d7c2c5069 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -108,7 +108,6 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn) return NT_STATUS_NO_MEMORY; } - sconn->smb2.sessions.list = NULL; sconn->smb2.seqnum_low = 0; sconn->smb2.credits_granted = 0; sconn->smb2.max_credits = lp_smb2_max_credits(); @@ -811,7 +810,7 @@ static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request /* Re-sign if needed. */ if (nreq->do_signing) { NTSTATUS status; - struct smbXsrv_session *x = nreq->session->smbXsrv; + struct smbXsrv_session *x = nreq->session; struct smbXsrv_connection *conn = x->connection; DATA_BLOB signing_key = x->global->channels[0].signing_key; @@ -1100,7 +1099,7 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev, if (req->do_signing) { NTSTATUS status; - struct smbXsrv_session *x = req->session->smbXsrv; + struct smbXsrv_session *x = req->session; struct smbXsrv_connection *conn = x->connection; DATA_BLOB signing_key = x->global->channels[0].signing_key; @@ -1203,8 +1202,9 @@ static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req) int i = req->current_idx; uint32_t in_flags; uint32_t in_tid; - void *p; - struct smbd_smb2_tcon *tcon; + struct smbXsrv_tcon0 *tcon; + NTSTATUS status; + NTTIME now = timeval_to_nttime(&req->request_time); req->tcon = NULL; @@ -1217,19 +1217,18 @@ static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req) in_tid = req->last_tid; } - /* lookup an existing session */ - p = idr_find(req->session->tcons.idtree, in_tid); - if (p == NULL) { - return NT_STATUS_NETWORK_NAME_DELETED; + status = smb2srv_tcon_lookup(req->session, + in_tid, now, &tcon); + if (!NT_STATUS_IS_OK(status)) { + return status; } - tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon); - if (!change_to_user(tcon->compat_conn,req->session->vuid)) { + if (!change_to_user(tcon->compat, req->session->compat->vuid)) { return NT_STATUS_ACCESS_DENIED; } /* should we pass FLAG_CASELESS_PATHNAMES here? */ - if (!set_current_service(tcon->compat_conn, 0, true)) { + if (!set_current_service(tcon->compat, 0, true)) { return NT_STATUS_ACCESS_DENIED; } @@ -1249,8 +1248,8 @@ static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req) int i = req->current_idx; uint32_t in_flags; uint64_t in_session_id; - struct smbd_smb2_session *session; - struct smbXsrv_session *smbXsrv; + struct smbXsrv_session *session; + struct auth_session_info *session_info; NTSTATUS status; NTTIME now = timeval_to_nttime(&req->request_time); @@ -1269,18 +1268,19 @@ static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req) /* lookup an existing session */ status = smb2srv_session_lookup(req->sconn->conn, in_session_id, now, - &smbXsrv); + &session); if (!NT_STATUS_IS_OK(status)) { return status; } - session = smbXsrv->smb2sess; - if (!NT_STATUS_IS_OK(session->status)) { - return NT_STATUS_ACCESS_DENIED; + + session_info = session->global->auth_session_info; + if (session_info == NULL) { + return NT_STATUS_INVALID_HANDLE; } - set_current_user_info(session->session_info->unix_info->sanitized_username, - session->session_info->unix_info->unix_name, - session->session_info->info->domain_name); + set_current_user_info(session_info->unix_info->sanitized_username, + session_info->unix_info->unix_name, + session_info->info->domain_name); req->session = session; req->last_session_id = in_session_id; @@ -1445,9 +1445,7 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) * we defer the check of the session_status */ session_status = smbd_smb2_request_check_session(req); - if (req->session) { - x = req->session->smbXsrv; - } + x = req->session; req->do_signing = false; if (flags & SMB2_HDR_FLAG_SIGNED) { @@ -1949,7 +1947,7 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) if (req->do_signing) { NTSTATUS status; - struct smbXsrv_session *x = req->session->smbXsrv; + struct smbXsrv_session *x = req->session; struct smbXsrv_connection *conn = x->connection; DATA_BLOB signing_key = x->global->channels[0].signing_key; diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index 9aa73d39cac..dc01fc38bd8 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -174,33 +174,7 @@ static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq) } } -static int smbd_smb2_session_destructor(struct smbd_smb2_session *session) -{ - if (session->sconn == NULL) { - return 0; - } - - file_close_user(session->sconn, session->vuid); - - /* first free all tcons */ - while (session->tcons.list) { - talloc_free(session->tcons.list); - } - - DLIST_REMOVE(session->sconn->smb2.sessions.list, session); - invalidate_vuid(session->sconn, session->vuid); - - session->vuid = 0; - session->status = NT_STATUS_USER_SESSION_DELETED; - session->sconn = NULL; - - session->smbXsrv->compat = NULL; - TALLOC_FREE(session->smbXsrv); - - return 0; -} - -static NTSTATUS smbd_smb2_auth_generic_return(struct smbd_smb2_session *session, +static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, struct smbd_smb2_request *smb2req, uint8_t in_security_mode, uint64_t in_previous_session_id, @@ -211,16 +185,24 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbd_smb2_session *session, NTSTATUS status; bool guest = false; uint8_t session_key[16]; - struct smbXsrv_session *x = session->smbXsrv; - struct auth_session_info *session_info = session->session_info; - struct smbXsrv_connection *conn = x->connection; + struct smbXsrv_session *x = session; + struct auth_session_info *session_info; + struct smbXsrv_connection *conn = session->connection; if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) || lp_server_signing() == SMB_SIGNING_REQUIRED) { x->global->signing_required = true; } - if (security_session_user_level(session->session_info, NULL) < SECURITY_USER) { + status = gensec_session_info(session->gensec, + session->global, + &session_info); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(session); + return status; + } + + if (security_session_user_level(session_info, NULL) < SECURITY_USER) { /* we map anonymous to guest internally */ *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST; *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL; @@ -230,8 +212,8 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbd_smb2_session *session, } ZERO_STRUCT(session_key); - memcpy(session_key, session->session_info->session_key.data, - MIN(session->session_info->session_key.length, sizeof(session_key))); + memcpy(session_key, session_info->session_key.data, + MIN(session_info->session_key.length, sizeof(session_key))); x->global->signing_key = data_blob_talloc(x->global, session_key, @@ -286,55 +268,53 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbd_smb2_session *session, return NT_STATUS_NO_MEMORY; } - session->compat_vuser = talloc_zero(session, struct user_struct); - if (session->compat_vuser == NULL) { + session->compat = talloc_zero(session, struct user_struct); + if (session->compat == NULL) { TALLOC_FREE(session); return NT_STATUS_NO_MEMORY; } - session->compat_vuser->gensec_security = session->gensec_security; - session->compat_vuser->homes_snum = -1; - session->compat_vuser->session_info = session->session_info; - session->compat_vuser->session_keystr = NULL; - session->compat_vuser->vuid = session->vuid; - DLIST_ADD(session->sconn->users, session->compat_vuser); - session->sconn->num_users++; + session->compat->session = session; + session->compat->homes_snum = -1; + session->compat->session_info = session_info; + session->compat->session_keystr = NULL; + session->compat->vuid = session->global->session_wire_id; + DLIST_ADD(smb2req->sconn->users, session->compat); + smb2req->sconn->num_users++; - if (security_session_user_level(session->session_info, NULL) >= SECURITY_USER) { - session->compat_vuser->homes_snum = - register_homes_share(session->session_info->unix_info->unix_name); + if (security_session_user_level(session_info, NULL) >= SECURITY_USER) { + session->compat->homes_snum = + register_homes_share(session_info->unix_info->unix_name); } - if (!session_claim(session->sconn, session->compat_vuser)) { + if (!session_claim(smb2req->sconn, session->compat)) { DEBUG(1, ("smb2: Failed to claim session " "for vuid=%llu\n", - (unsigned long long)session->compat_vuser->vuid)); + (unsigned long long)session->compat->vuid)); TALLOC_FREE(session); return NT_STATUS_LOGON_FAILURE; } - set_current_user_info(session->session_info->unix_info->sanitized_username, - session->session_info->unix_info->unix_name, - session->session_info->info->domain_name); + set_current_user_info(session_info->unix_info->sanitized_username, + session_info->unix_info->unix_name, + session_info->info->domain_name); reload_services(smb2req->sconn, conn_snum_used, true); - session->smbXsrv->status = NT_STATUS_OK; - session->smbXsrv->global->auth_session_info = session->session_info; - session->smbXsrv->global->auth_session_info_seqnum += 1; - session->smbXsrv->global->channels[0].auth_session_info_seqnum = - session->smbXsrv->global->auth_session_info_seqnum; + session->status = NT_STATUS_OK; + session->global->auth_session_info = session_info; + session->global->auth_session_info_seqnum += 1; + session->global->channels[0].auth_session_info_seqnum = + session->global->auth_session_info_seqnum; - status = smbXsrv_session_update(session->smbXsrv); + status = smbXsrv_session_update(session); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n", - (unsigned long long)session->compat_vuser->vuid, + (unsigned long long)session->compat->vuid, nt_errstr(status))); TALLOC_FREE(session); return NT_STATUS_LOGON_FAILURE; } - session->status = NT_STATUS_OK; - /* * we attach the session to the request * so that the response can be signed @@ -346,12 +326,12 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbd_smb2_session *session, global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32); - *out_session_id = session->vuid; + *out_session_id = session->global->session_wire_id; return NT_STATUS_OK; } -static NTSTATUS smbd_smb2_auth_generic(struct smbd_smb2_session *session, +static NTSTATUS smbd_smb2_auth_generic(struct smbXsrv_session *session, struct smbd_smb2_request *smb2req, uint8_t in_security_mode, uint64_t in_previous_session_id, @@ -364,18 +344,20 @@ static NTSTATUS smbd_smb2_auth_generic(struct smbd_smb2_session *session, *out_security_buffer = data_blob_null; - if (session->gensec_security == NULL) { - status = auth_generic_prepare(session, session->sconn->remote_address, - &session->gensec_security); + if (session->gensec == NULL) { + status = auth_generic_prepare(session, + session->connection->remote_address, + &session->gensec); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(session); return status; } - gensec_want_feature(session->gensec_security, GENSEC_FEATURE_SESSION_KEY); - gensec_want_feature(session->gensec_security, GENSEC_FEATURE_UNIX_TOKEN); + gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY); + gensec_want_feature(session->gensec, GENSEC_FEATURE_UNIX_TOKEN); - status = gensec_start_mech_by_oid(session->gensec_security, GENSEC_OID_SPNEGO); + status = gensec_start_mech_by_oid(session->gensec, + GENSEC_OID_SPNEGO); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(session); return status; @@ -383,7 +365,7 @@ static NTSTATUS smbd_smb2_auth_generic(struct smbd_smb2_session *session, } become_root(); - status = gensec_update(session->gensec_security, + status = gensec_update(session->gensec, smb2req, NULL, in_security_buffer, out_security_buffer); @@ -395,19 +377,9 @@ static NTSTATUS smbd_smb2_auth_generic(struct smbd_smb2_session *session, } if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - *out_session_id = session->vuid; - return status; - } - - status = gensec_session_info(session->gensec_security, - session, - &session->session_info); - - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(session); + *out_session_id = session->global->session_wire_id; return status; } - *out_session_id = session->vuid; return smbd_smb2_auth_generic_return(session, smb2req, @@ -428,7 +400,6 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req, DATA_BLOB *out_security_buffer, uint64_t *out_session_id) { - struct smbd_smb2_session *smb2sess; struct smbXsrv_session *session; NTSTATUS status; NTTIME now = timeval_to_nttime(&smb2req->request_time); @@ -438,33 +409,11 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req, if (in_session_id == 0) { /* create a new session */ - smb2sess = talloc_zero(smb2req->sconn, struct smbd_smb2_session); - if (smb2sess == NULL) { - return NT_STATUS_NO_MEMORY; - } - status = smbXsrv_session_create(smb2req->sconn->conn, now, &session); if (!NT_STATUS_IS_OK(status)) { return status; } - smb2sess->smbXsrv = session; - session->smb2sess = smb2sess; - talloc_set_destructor(smb2sess, smbd_smb2_session_destructor); - - smb2sess->status = NT_STATUS_MORE_PROCESSING_REQUIRED; - smb2sess->vuid = session->global->session_wire_id; - - smb2sess->tcons.idtree = idr_init(smb2sess); - if (smb2sess->tcons.idtree == NULL) { - return NT_STATUS_NO_MEMORY; - } - smb2sess->tcons.limit = 0x0000FFFE; - smb2sess->tcons.list = NULL; - - DLIST_ADD_END(smb2req->sconn->smb2.sessions.list, smb2sess, - struct smbd_smb2_session *); - smb2sess->sconn = smb2req->sconn; } else { status = smb2srv_session_lookup(smb2req->sconn->conn, in_session_id, now, @@ -473,18 +422,11 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req, return NT_STATUS_REQUEST_NOT_ACCEPTED; } if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - return status; } - - smb2sess = session->smb2sess; - } - - if (NT_STATUS_IS_OK(smb2sess->status)) { - return NT_STATUS_REQUEST_NOT_ACCEPTED; } - return smbd_smb2_auth_generic(smb2sess, + return smbd_smb2_auth_generic(session, smb2req, in_security_mode, in_previous_session_id, @@ -596,9 +538,19 @@ NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req) /* * TODO: cancel all outstanding requests on the session - * and delete all tree connections. */ - smbd_smb2_session_destructor(req->session); + status = smbXsrv_session_logoff(req->session); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("smbd_smb2_request_process_logoff: " + "smbXsrv_session_logoff() failed: %s\n", + nt_errstr(status))); + /* + * If we hit this case, there is something completely + * wrong, so we better disconnect the transport connection. + */ + return status; + } + /* * we may need to sign the response, so we need to keep * the session until the response is sent to the wire. diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c index c7652f6644b..32fbcca43c9 100644 --- a/source3/smbd/smb2_setinfo.c +++ b/source3/smbd/smb2_setinfo.c @@ -172,7 +172,7 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx, struct tevent_req *req = NULL; struct smbd_smb2_setinfo_state *state = NULL; struct smb_request *smbreq = NULL; - connection_struct *conn = smb2req->tcon->compat_conn; + connection_struct *conn = smb2req->tcon->compat; NTSTATUS status; req = tevent_req_create(mem_ctx, &state, diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c index 14294aefaf4..ceb145ff63a 100644 --- a/source3/smbd/smb2_tcon.c +++ b/source3/smbd/smb2_tcon.c @@ -169,27 +169,6 @@ static void smbd_smb2_request_tcon_done(struct tevent_req *subreq) } } -static int smbd_smb2_tcon_destructor(struct smbd_smb2_tcon *tcon) -{ - if (tcon->session == NULL) { - return 0; - } - - idr_remove(tcon->session->tcons.idtree, tcon->tid); - DLIST_REMOVE(tcon->session->tcons.list, tcon); - - if (tcon->compat_conn) { - set_current_service(tcon->compat_conn, 0, true); - close_cnum(tcon->compat_conn, tcon->session->vuid); - } - - tcon->compat_conn = NULL; - tcon->tid = 0; - tcon->session = NULL; - - return 0; -} - static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req, const char *in_path, uint8_t *out_share_type, @@ -201,11 +180,12 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req, const char *share = in_path; char *service = NULL; int snum = -1; - struct smbd_smb2_tcon *tcon; + struct smbXsrv_tcon *tcon; + NTTIME now = timeval_to_nttime(&req->request_time); connection_struct *compat_conn = NULL; - struct user_struct *compat_vuser = req->session->compat_vuser; - int id; + struct user_struct *compat_vuser = req->session->compat; NTSTATUS status; + const char *share_name = NULL; if (strncmp(share, "\\\\", 2) == 0) { const char *p = strchr(share+2, '\\'); @@ -253,39 +233,42 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req, } /* create a new tcon as child of the session */ - tcon = talloc_zero(req->session, struct smbd_smb2_tcon); - if (tcon == NULL) { - return NT_STATUS_NO_MEMORY; - } - id = idr_get_new_random(req->session->tcons.idtree, - tcon, - req->session->tcons.limit); - if (id == -1) { - TALLOC_FREE(tcon); - return NT_STATUS_INSUFFICIENT_RESOURCES; + status = smb2srv_tcon_create(req->session, now, &tcon); + if (!NT_STATUS_IS_OK(status)) { + return status; } - tcon->tid = id; - tcon->snum = snum; - - DLIST_ADD_END(req->session->tcons.list, tcon, - struct smbd_smb2_tcon *); - tcon->session = req->session; - talloc_set_destructor(tcon, smbd_smb2_tcon_destructor); compat_conn = make_connection_smb2(req->sconn, - tcon, - req->session->compat_vuser, + tcon, snum, + req->session->compat, "???", &status); if (compat_conn == NULL) { TALLOC_FREE(tcon); return status; } - tcon->compat_conn = talloc_move(tcon, &compat_conn); - if (IS_PRINT(tcon->compat_conn)) { + share_name = lp_servicename(SNUM(compat_conn)); + tcon->global->share_name = talloc_strdup(tcon->global, share_name); + if (tcon->global->share_name == NULL) { + conn_free(compat_conn); + TALLOC_FREE(tcon); + return NT_STATUS_NO_MEMORY; + } + + tcon->compat = talloc_move(tcon, &compat_conn); + + tcon->status = NT_STATUS_OK; + + status = smbXsrv_tcon_update(tcon); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(tcon); + return status; + } + + if (IS_PRINT(tcon->compat)) { *out_share_type = SMB2_SHARE_TYPE_PRINT; - } else if (IS_IPC(tcon->compat_conn)) { + } else if (IS_IPC(tcon->compat)) { *out_share_type = SMB2_SHARE_TYPE_PIPE; } else { *out_share_type = SMB2_SHARE_TYPE_DISK; @@ -293,14 +276,14 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req, *out_share_flags = 0; - if (lp_msdfs_root(SNUM(tcon->compat_conn)) && lp_host_msdfs()) { + if (lp_msdfs_root(SNUM(tcon->compat)) && lp_host_msdfs()) { *out_share_flags |= (SMB2_SHAREFLAG_DFS|SMB2_SHAREFLAG_DFS_ROOT); *out_capabilities = SMB2_SHARE_CAP_DFS; } else { *out_capabilities = 0; } - switch(lp_csc_policy(SNUM(tcon->compat_conn))) { + switch(lp_csc_policy(SNUM(tcon->compat))) { case CSC_POLICY_MANUAL: break; case CSC_POLICY_DOCUMENTS: @@ -316,14 +299,14 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req, break; } - if (lp_hideunreadable(SNUM(tcon->compat_conn)) || - lp_hideunwriteable_files(SNUM(tcon->compat_conn))) { + if (lp_hideunreadable(SNUM(tcon->compat)) || + lp_hideunwriteable_files(SNUM(tcon->compat))) { *out_share_flags |= SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM; } - *out_maximal_access = tcon->compat_conn->share_access; + *out_maximal_access = tcon->compat->share_access; - *out_tree_id = tcon->tid; + *out_tree_id = tcon->global->tcon_wire_id; return NT_STATUS_OK; } @@ -406,8 +389,19 @@ NTSTATUS smbd_smb2_request_process_tdis(struct smbd_smb2_request *req) /* * TODO: cancel all outstanding requests on the tcon - * and delete all file handles. */ + status = smbXsrv_tcon_disconnect(req->tcon, req->tcon->compat->vuid); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("smbd_smb2_request_process_tdis: " + "smbXsrv_tcon_disconnect() failed: %s\n", + nt_errstr(status))); + /* + * If we hit this case, there is something completely + * wrong, so we better disconnect the transport connection. + */ + return status; + } + TALLOC_FREE(req->tcon); outbody = data_blob_talloc(req->out.vector, NULL, 0x04); diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c index 778f15a567b..0150b0cd25d 100644 --- a/source3/smbd/smb2_write.c +++ b/source3/smbd/smb2_write.c @@ -246,7 +246,7 @@ static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx, struct tevent_req *req = NULL; struct smbd_smb2_write_state *state = NULL; struct smb_request *smbreq = NULL; - connection_struct *conn = smb2req->tcon->compat_conn; + connection_struct *conn = smb2req->tcon->compat; ssize_t nwritten; struct lock_struct lock; -- 2.11.4.GIT