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;
[ignore] gensec_security *gensec;
[ignore] user_struct *compat;
[ignore] smbXsrv_tcon_table *tcon_table;
- [ignore] smbd_smb2_session *smb2sess;
} smbXsrv_session0;
typedef union {
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;
}
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 */
return NULL;
}
- if (smb2req->tcon->compat_conn != fsp->conn) {
+ if (smb2req->tcon->compat != fsp->conn) {
return NULL;
}
return NULL;
}
- if (smb2req->session->vuid != fsp->vuid) {
+ if (smb2req->session->compat == NULL) {
+ return NULL;
+ }
+
+ if (smb2req->session->compat->vuid != fsp->vuid) {
return NULL;
}
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);
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;
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;
struct tevent_queue *send_queue;
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;
void invalidate_all_vuids(struct smbd_server_connection *sconn)
{
if (sconn->using_smb2) {
+ smbXsrv_session_logoff_all(sconn->conn);
return;
}
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);
****************************************************************************/
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)
*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)) {
{
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;
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;
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);
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;
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,
}
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 |
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;
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;
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();
/* 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;
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;
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;
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;
}
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);
/* 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;
* 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) {
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;
}
}
-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,
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;
}
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,
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
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,
*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;
}
become_root();
- status = gensec_update(session->gensec_security,
+ status = gensec_update(session->gensec,
smb2req, NULL,
in_security_buffer,
out_security_buffer);
}
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,
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);
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,
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,
/*
* 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.
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,
}
}
-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,
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, '\\');
}
/* 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;
*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:
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;
}
/*
* 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);
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;