diff options
Diffstat (limited to 'source3/smbd/conn.c')
-rw-r--r-- | source3/smbd/conn.c | 222 |
1 files changed, 35 insertions, 187 deletions
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index c4ab5c1793..da4ed9966c 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -22,7 +22,6 @@ #include "includes.h" #include "smbd/smbd.h" #include "smbd/globals.h" -#include "rpc_server/rpc_ncacn_np.h" /* The connections bitmap is expanded in increments of BITMAP_BLOCK_SZ. The * maximum size of the bitmap is the largest positive integer, but you will hit @@ -212,142 +211,52 @@ find_again: } /**************************************************************************** - Close all conn structures. - Return true if any were closed. + Clear a vuid out of the connection's vuid cache ****************************************************************************/ -bool conn_close_all(struct smbd_server_connection *sconn) +static void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid) { - bool ret = false; - 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; - TALLOC_FREE(tcon); - ret = true; - } - } - } else { - /* SMB1 */ - connection_struct *conn, *next; - - for (conn=sconn->smb1.tcons.Connections;conn;conn=next) { - next=conn->next; - set_current_service(conn, 0, True); - close_cnum(conn, conn->vuid); - ret = true; - } - } - return ret; -} - -/**************************************************************************** - Update last used timestamps. -****************************************************************************/ - -static void conn_lastused_update(struct smbd_server_connection *sconn,time_t t) -{ - if (sconn->using_smb2) { - /* SMB2 */ - struct smbd_smb2_session *sess; - for (sess = sconn->smb2.sessions.list; sess; sess = sess->next) { - struct smbd_smb2_tcon *ptcon; - - for (ptcon = sess->tcons.list; ptcon; ptcon = ptcon->next) { - connection_struct *conn = ptcon->compat_conn; - /* Update if connection wasn't idle. */ - if (conn && conn->lastused != conn->lastused_count) { - conn->lastused = t; - conn->lastused_count = t; - } - } - } - } else { - /* SMB1 */ - connection_struct *conn; - for (conn=sconn->smb1.tcons.Connections;conn;conn=conn->next) { - /* Update if connection wasn't idle. */ - if (conn->lastused != conn->lastused_count) { - conn->lastused = t; - conn->lastused_count = t; - } - } - } -} - -/**************************************************************************** - Idle inactive connections. -****************************************************************************/ - -bool conn_idle_all(struct smbd_server_connection *sconn, time_t t) -{ - int deadtime = lp_deadtime()*60; - - conn_lastused_update(sconn, t); - - if (deadtime <= 0) { - deadtime = DEFAULT_SMBD_TIMEOUT; - } - - if (sconn->using_smb2) { - /* SMB2 */ - struct smbd_smb2_session *sess; - for (sess = sconn->smb2.sessions.list; sess; sess = sess->next) { - struct smbd_smb2_tcon *ptcon; - - for (ptcon = sess->tcons.list; ptcon; ptcon = ptcon->next) { - time_t age; - connection_struct *conn = ptcon->compat_conn; - - if (conn == NULL) { - continue; - } - - age = t - conn->lastused; - /* close dirptrs on connections that are idle */ - if (age > DPTR_IDLE_TIMEOUT) { - dptr_idlecnum(conn); - } - - if (conn->num_files_open > 0 || age < deadtime) { - return false; - } - } - } - } else { - /* SMB1 */ - connection_struct *conn; - for (conn=sconn->smb1.tcons.Connections;conn;conn=conn->next) { - time_t age = t - conn->lastused; - - /* close dirptrs on connections that are idle */ - if (age > DPTR_IDLE_TIMEOUT) { - dptr_idlecnum(conn); - } + int i; - if (conn->num_files_open > 0 || age < deadtime) { - return false; + for (i=0; i<VUID_CACHE_SIZE; i++) { + struct vuid_cache_entry *ent; + + ent = &conn->vuid_cache.array[i]; + + if (ent->vuid == vuid) { + ent->vuid = UID_FIELD_INVALID; + /* + * We need to keep conn->session_info around + * if it's equal to ent->session_info as a SMBulogoff + * is often followed by a SMBtdis (with an invalid + * vuid). The debug code (or regular code in + * vfs_full_audit) wants to refer to the + * conn->session_info pointer to print debug + * statements. Theoretically this is a bug, + * as once the vuid is gone the session_info + * on the conn struct isn't valid any more, + * but there's enough code that assumes + * conn->session_info is never null that + * it's easier to hold onto the old pointer + * until we get a new sessionsetupX. + * As everything is hung off the + * conn pointer as a talloc context we're not + * leaking memory here. See bug #6315. JRA. + */ + if (conn->session_info == ent->session_info) { + ent->session_info = NULL; + } else { + TALLOC_FREE(ent->session_info); } + ent->read_only = False; } } - - /* - * Check all pipes for any open handles. We cannot - * idle with a handle open. - */ - if (check_open_pipes()) { - return false; - } - - return true; } /**************************************************************************** Clear a vuid out of the validity cache, and as the 'owner' of a connection. + + Called from invalidate_vuid() ****************************************************************************/ void conn_clear_vuid_caches(struct smbd_server_connection *sconn,uint16_t vuid) @@ -451,64 +360,3 @@ void conn_free(connection_struct *conn) conn_free_internal(conn); } - -/**************************************************************************** - Receive a smbcontrol message to forcibly unmount a share. - The message contains just a share name and all instances of that - share are unmounted. - The special sharename '*' forces unmount of all shares. -****************************************************************************/ - -void msg_force_tdis(struct messaging_context *msg, - void *private_data, - uint32_t msg_type, - struct server_id server_id, - DATA_BLOB *data) -{ - struct smbd_server_connection *sconn; - connection_struct *conn, *next; - fstring sharename; - - sconn = msg_ctx_to_sconn(msg); - if (sconn == NULL) { - DEBUG(1, ("could not find sconn\n")); - return; - } - - fstrcpy(sharename, (const char *)data->data); - - if (strcmp(sharename, "*") == 0) { - DEBUG(1,("Forcing close of all shares\n")); - conn_close_all(sconn); - return; - } - - 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); - } - } - } - } else { - /* SMB1 */ - for (conn=sconn->smb1.tcons.Connections;conn;conn=next) { - next=conn->next; - if (strequal(lp_servicename(SNUM(conn)), sharename)) { - DEBUG(1,("Forcing close of share %s cnum=%d\n", - sharename, conn->cnum)); - close_cnum(conn, (uint16)-1); - } - } - } -} |