diff options
-rw-r--r-- | source3/Makefile.in | 2 | ||||
-rw-r--r-- | source3/smbd/conn.c | 222 | ||||
-rw-r--r-- | source3/smbd/conn_idle.c | 207 | ||||
-rw-r--r-- | source3/smbd/conn_msg.c | 49 | ||||
-rw-r--r-- | source3/smbd/proto.h | 2 | ||||
-rw-r--r-- | source3/smbd/uid.c | 44 | ||||
-rwxr-xr-x | source3/wscript_build | 13 |
7 files changed, 303 insertions, 236 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 564c37a7be..366ecffc86 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -890,7 +890,7 @@ BUILDOPT_OBJ = smbd/build_options.o SMBD_OBJ_SRV = smbd/server_reload.o \ smbd/files.o smbd/connection.o \ smbd/utmp.o smbd/session.o \ - smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o \ + smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o smbd/conn_idle.o smbd/conn_msg.o \ smbd/share_access.o smbd/fileio.o \ smbd/ipc.o smbd/lanman.o smbd/negprot.o \ smbd/message.o smbd/nttrans.o smbd/pipes.o \ 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); - } - } - } -} diff --git a/source3/smbd/conn_idle.c b/source3/smbd/conn_idle.c new file mode 100644 index 0000000000..46f5b7b111 --- /dev/null +++ b/source3/smbd/conn_idle.c @@ -0,0 +1,207 @@ +/* + Unix SMB/CIFS implementation. + Manage connections_struct structures + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Alexander Bokovoy 2002 + Copyright (C) Jeremy Allison 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "smbd/smbd.h" +#include "smbd/globals.h" +#include "rpc_server/rpc_ncacn_np.h" + +/**************************************************************************** + 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); + } + + if (conn->num_files_open > 0 || age < deadtime) { + return false; + } + } + } + + /* + * Check all pipes for any open handles. We cannot + * idle with a handle open. + */ + if (check_open_pipes()) { + return false; + } + + return true; +} + +/**************************************************************************** + Close all conn structures. + Return true if any were closed. +****************************************************************************/ + +bool conn_close_all(struct smbd_server_connection *sconn) +{ + 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; +} + + +/**************************************************************************** + Forcibly unmount a share. + All instances of the parameter 'sharename' share are unmounted. + The special sharename '*' forces unmount of all shares. +****************************************************************************/ + +void conn_force_tdis(struct smbd_server_connection *sconn, const char *sharename) +{ + connection_struct *conn, *next; + + 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); + } + } + } +} diff --git a/source3/smbd/conn_msg.c b/source3/smbd/conn_msg.c new file mode 100644 index 0000000000..ba03823667 --- /dev/null +++ b/source3/smbd/conn_msg.c @@ -0,0 +1,49 @@ +/* + Unix SMB/CIFS implementation. + Manage connections_struct structures + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Alexander Bokovoy 2002 + Copyright (C) Jeremy Allison 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "smbd/smbd.h" +#include "smbd/globals.h" + +/**************************************************************************** + 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; + const char *sharename = (const char *)data->data; + + sconn = msg_ctx_to_sconn(msg); + if (sconn == NULL) { + DEBUG(1, ("could not find sconn\n")); + return; + } + + return conn_force_tdis(sconn, sharename); +} diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 5b45574bc5..b1ebf994cf 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -102,6 +102,7 @@ bool conn_close_all(struct smbd_server_connection *sconn); bool conn_idle_all(struct smbd_server_connection *sconn, time_t t); void conn_clear_vuid_caches(struct smbd_server_connection *sconn, uint16 vuid); void conn_free(connection_struct *conn); +void conn_force_tdis(struct smbd_server_connection *sconn, const char *sharename); void msg_force_tdis(struct messaging_context *msg, void *private_data, uint32_t msg_type, @@ -1049,7 +1050,6 @@ void reply_transs2(struct smb_request *req); /* The following definitions come from smbd/uid.c */ bool change_to_guest(void); -void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid); bool change_to_user(connection_struct *conn, uint16 vuid); bool change_to_user_by_session(connection_struct *conn, const struct auth_serversupplied_info *session_info); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 7b04713bab..fb05a6ce98 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -182,50 +182,6 @@ static bool check_user_ok(connection_struct *conn, } /**************************************************************************** - Clear a vuid out of the connection's vuid cache - This is only called on SMBulogoff. -****************************************************************************/ - -void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid) -{ - int i; - - 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; - } - } -} - -/**************************************************************************** Become the user of a connection number without changing the security context stack, but modify the current_user entries. ****************************************************************************/ diff --git a/source3/wscript_build b/source3/wscript_build index 5b89cf0427..89fa4ac768 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -347,7 +347,8 @@ BUILDOPT_SRC = '''smbd/build_options.c''' SMBD_SRC_SRV = '''smbd/server_reload.c smbd/files.c smbd/connection.c smbd/utmp.c smbd/session.c - smbd/dfree.c smbd/dir.c smbd/password.c smbd/conn.c + smbd/dfree.c smbd/dir.c smbd/password.c smbd/conn_msg.c + smbd/conn_idle.c smbd/share_access.c smbd/fileio.c smbd/ipc.c smbd/lanman.c smbd/negprot.c smbd/message.c smbd/nttrans.c smbd/pipes.c @@ -739,7 +740,7 @@ bld.SAMBA3_SUBSYSTEM('PARAM_UTIL', bld.SAMBA3_SUBSYSTEM('PARAM_WITHOUT_REG', source=PARAM_WITHOUT_REG_SRC, - deps='''PARAM_UTIL''', + deps='''PARAM_UTIL smbd_conn USER_UTIL PRINTING''', vars=locals()) bld.SAMBA3_LIBRARY('param', @@ -868,6 +869,12 @@ bld.SAMBA3_LIBRARY('smbconf', public_headers='../lib/smbconf/smbconf.h', vnum='0') +bld.SAMBA3_LIBRARY('smbd_conn', + source='smbd/conn.c', + deps='samba3core string_init', + allow_undefined_symbols=False, + private_library=True) + bld.SAMBA3_LIBRARY('smbd_base', source=SMBD_SRC_BASE, deps='''tdb tevent dl krb5 ldap gssapi gssapi_krb5 @@ -879,7 +886,7 @@ bld.SAMBA3_LIBRARY('smbd_base', smbconf REG_FULL FNAME_UTIL LIBCLI_SAMR LIBCLI_LSA3 LIBRPCCLI_NETLOGON LIBCLI_SPOOLSS RPC_NDR_SRVSVC npa_tstream INIT_NETLOGON INIT_SAMR - LIBCLI_SMB_COMMON RPC_SERVER + LIBCLI_SMB_COMMON RPC_SERVER smbd_conn ''', private_library=True, vars=locals()) |