diff options
Diffstat (limited to 'source3/smbd')
72 files changed, 1349 insertions, 1077 deletions
diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 682d042806..db2926b4a4 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -21,6 +21,7 @@ #include "includes.h" #include "smbd/smbd.h" #include "smbd/globals.h" +#include "../lib/util/tevent_ntstatus.h" #if defined(WITH_AIO) @@ -80,8 +81,8 @@ static bool initialize_async_io_handler(void) } tried_signal_setup = true; - aio_signal_event = tevent_add_signal(smbd_event_context(), - smbd_event_context(), + aio_signal_event = tevent_add_signal(server_event_context(), + server_event_context(), RT_SIGNAL_AIO, SA_SIGINFO, smbd_aio_signal_handler, NULL); @@ -115,7 +116,7 @@ static struct aio_extra *create_aio_extra(TALLOC_CTX *mem_ctx, files_struct *fsp, size_t buflen) { - struct aio_extra *aio_ex = TALLOC_ZERO_P(mem_ctx, struct aio_extra); + struct aio_extra *aio_ex = talloc_zero(mem_ctx, struct aio_extra); if (!aio_ex) { return NULL; @@ -250,7 +251,7 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn, NTSTATUS schedule_aio_write_and_X(connection_struct *conn, struct smb_request *smbreq, - files_struct *fsp, char *data, + files_struct *fsp, const char *data, SMB_OFF_T startpos, size_t numtowrite) { @@ -328,7 +329,7 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn, /* Now set up the aio record for the write call. */ a->aio_fildes = fsp->fh->fd; - a->aio_buf = data; + a->aio_buf = discard_const_p(char, data); a->aio_nbytes = numtowrite; a->aio_offset = startpos; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; @@ -1029,7 +1030,7 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn, NTSTATUS schedule_aio_write_and_X(connection_struct *conn, struct smb_request *smbreq, - files_struct *fsp, char *data, + files_struct *fsp, const char *data, SMB_OFF_T startpos, size_t numtowrite) { diff --git a/source3/smbd/avahi_register.c b/source3/smbd/avahi_register.c index 05bd6038f4..368168d41d 100644 --- a/source3/smbd/avahi_register.c +++ b/source3/smbd/avahi_register.c @@ -88,7 +88,7 @@ static void avahi_client_callback(AvahiClient *c, AvahiClientState status, } if (avahi_entry_group_add_service( state->entry_group, AVAHI_IF_UNSPEC, - AVAHI_PROTO_UNSPEC, 0, global_myname(), + AVAHI_PROTO_UNSPEC, 0, lp_netbios_name(), "_smb._tcp", NULL, NULL, state->port, NULL) < 0) { error = avahi_client_errno(c); DEBUG(10, ("avahi_entry_group_add_service failed: " diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index c208234bdc..d9c1fb2d3b 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -139,7 +139,7 @@ static bool recalc_brl_timeout(struct smbd_server_connection *sconn) (int)from_now.tv_sec, (int)from_now.tv_usec)); } - sconn->smb1.locks.brl_timeout = event_add_timed(smbd_event_context(), + sconn->smb1.locks.brl_timeout = event_add_timed(server_event_context(), NULL, next_timeout, brl_timeout_fn, sconn); if (sconn->smb1.locks.brl_timeout == NULL) { @@ -208,8 +208,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, blr->expire_time.tv_sec = 0; blr->expire_time.tv_usec = 0; /* Never expire. */ } else { - blr->expire_time = timeval_current_ofs(lock_timeout/1000, - (lock_timeout % 1000) * 1000); + blr->expire_time = timeval_current_ofs_msec(lock_timeout); } blr->lock_num = lock_num; blr->smblctx = smblctx; @@ -337,7 +336,7 @@ static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS stat uint8_t *data; int i; - data = (uint8_t *)blr->req->buf + data = discard_const_p(uint8_t, blr->req->buf) + ((large_file_format ? 20 : 10)*num_ulocks); /* @@ -429,7 +428,7 @@ static bool process_lockingX(struct blocking_lock_record *blr) uint8_t *data; NTSTATUS status = NT_STATUS_OK; - data = (uint8_t *)blr->req->buf + data = discard_const_p(uint8_t, blr->req->buf) + ((large_file_format ? 20 : 10)*num_ulocks); /* @@ -575,9 +574,9 @@ static bool blocking_lock_record_process(struct blocking_lock_record *blr) Called when a file is closed. *****************************************************************************/ -void cancel_pending_lock_requests_by_fid(files_struct *fsp, - struct byte_range_lock *br_lck, - enum file_close_type close_type) +void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp, + struct byte_range_lock *br_lck, + enum file_close_type close_type) { struct smbd_server_connection *sconn = fsp->conn->sconn; struct blocking_lock_record *blr, *blr_cancelled, *next = NULL; diff --git a/source3/smbd/close.c b/source3/smbd/close.c index aeed4e3c9d..52cfc111fb 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -283,7 +283,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, /* Ensure any pending write time updates are done. */ if (fsp->update_write_time_event) { - update_write_time_handler(smbd_event_context(), + update_write_time_handler(server_event_context(), fsp->update_write_time_event, timeval_current(), (void *)fsp); diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 16a0ee053e..a3f66b36be 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -53,10 +53,9 @@ int conn_num_open(struct smbd_server_connection *sconn) Check if a snum is in use. ****************************************************************************/ -bool conn_snum_used(int snum) +bool conn_snum_used(struct smbd_server_connection *sconn, + int snum) { - struct smbd_server_connection *sconn = smbd_server_conn; - if (sconn->using_smb2) { /* SMB2 */ struct smbd_smb2_session *sess; @@ -134,8 +133,8 @@ connection_struct *conn_new(struct smbd_server_connection *sconn) if (sconn->using_smb2) { /* SMB2 */ - if (!(conn=TALLOC_ZERO_P(NULL, connection_struct)) || - !(conn->params = TALLOC_P(conn, struct share_params))) { + if (!(conn=talloc_zero(NULL, connection_struct)) || + !(conn->params = talloc(conn, struct share_params))) { DEBUG(0,("TALLOC_ZERO() failed!\n")); TALLOC_FREE(conn); return NULL; @@ -189,8 +188,8 @@ find_again: return NULL; } - if (!(conn=TALLOC_ZERO_P(NULL, connection_struct)) || - !(conn->params = TALLOC_P(conn, struct share_params))) { + if (!(conn=talloc_zero(NULL, connection_struct)) || + !(conn->params = talloc(conn, struct share_params))) { DEBUG(0,("TALLOC_ZERO() failed!\n")); TALLOC_FREE(conn); return NULL; @@ -212,142 +211,52 @@ find_again: } /**************************************************************************** - 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; -} - -/**************************************************************************** - 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. + Clear a vuid out of the connection's vuid cache ****************************************************************************/ -bool conn_idle_all(struct smbd_server_connection *sconn, time_t t) +static void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid) { - 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..b0c968a680 --- /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; + } + + conn_force_tdis(sconn, sharename); +} diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 8560a5d211..7ed9518756 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -101,6 +101,7 @@ static int count_fn(struct db_record *rec, int count_current_connections( const char *sharename, bool clear ) { struct count_stat cs; + int ret; cs.curr_connections = 0; cs.name = sharename; @@ -111,10 +112,18 @@ int count_current_connections( const char *sharename, bool clear ) * as it leads to deadlock. */ - if (connections_forall(count_fn, &cs) == -1) { + /* + * become_root() because we might have to open connections.tdb + * via ctdb, which is not possible without root. + */ + become_root(); + ret = connections_forall(count_fn, &cs); + unbecome_root(); + + if (ret < 0) { DEBUG(0,("count_current_connections: traverse of " "connections.tdb failed\n")); - return False; + return 0; } return cs.curr_connections; diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 63c287cd41..03541880e1 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -207,7 +207,7 @@ uint64_t get_dfree_info(connection_struct *conn, /* No cached info or time to refresh. */ if (!dfc) { - dfc = TALLOC_P(conn, struct dfree_cached_info); + dfc = talloc(conn, struct dfree_cached_info); if (!dfc) { return dfree_ret; } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 5fc87a608f..fda7c34c57 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -92,7 +92,7 @@ bool make_dir_struct(TALLOC_CTX *ctx, return False; } - if ((mode & aDIR) != 0) { + if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) { size = 0; } @@ -872,15 +872,15 @@ bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype) uint32 mask; /* Check the "may have" search bits. */ - if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) + if (((mode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) != 0) return False; /* Check the "must have" bits, which are the may have bits shifted eight */ /* If must have bit is set, the file/dir can not be returned in search unless the matching file attribute is set */ - mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */ + mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */ if(mask) { - if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */ + if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))) == mask) /* check if matching attribute present */ return True; else return False; @@ -1342,7 +1342,7 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *mask, uint32 attr) { - struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir); + struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir); struct smbd_server_connection *sconn = conn->sconn; if (!dirp) { @@ -1386,7 +1386,7 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *mask, uint32 attr) { - struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir); + struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir); struct smbd_server_connection *sconn = conn->sconn; if (!dirp) { @@ -1559,7 +1559,7 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset) } if (dirp->name_cache == NULL) { - dirp->name_cache = TALLOC_ZERO_ARRAY( + dirp->name_cache = talloc_zero_array( dirp, struct name_cache_entry, dirp->name_cache_size); if (dirp->name_cache == NULL) { @@ -1625,8 +1625,8 @@ bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) Is this directory empty ? *****************************************************************/ -NTSTATUS can_delete_directory(struct connection_struct *conn, - const char *dirname) +NTSTATUS smbd_can_delete_directory(struct connection_struct *conn, + const char *dirname) { NTSTATUS status = NT_STATUS_OK; long dirpos = 0; diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 2869b6d781..8e80a588c5 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -96,7 +96,7 @@ static int dmapi_init_session(struct smbd_dmapi_context *ctx) do { dm_sessid_t *new_sessions; nsessions *= 2; - new_sessions = TALLOC_REALLOC_ARRAY(tmp_ctx, sessions, + new_sessions = talloc_realloc(tmp_ctx, sessions, dm_sessid_t, nsessions); if (new_sessions == NULL) { talloc_free(tmp_ctx); @@ -289,7 +289,7 @@ uint32 dmapi_file_flags(const char * const path) become_root(); #endif - err = dm_path_to_handle(CONST_DISCARD(char *, path), + err = dm_path_to_handle(discard_const_p(char, path), &dm_handle, &dm_handle_len); if (err < 0) { DEBUG(DMAPI_TRACE, ("dm_path_to_handle(%s): %s\n", @@ -308,7 +308,7 @@ uint32 dmapi_file_flags(const char * const path) set_effective_capability(DMAPI_ACCESS_CAPABILITY); - err = dm_path_to_handle(CONST_DISCARD(char *, path), + err = dm_path_to_handle(discard_const_p(char, path), &dm_handle, &dm_handle_len); if (err < 0) { DEBUG(DMAPI_TRACE, diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index a9b6dfef78..823d44d0aa 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -41,7 +41,7 @@ static int set_link_read_only_flag(const SMB_STRUCT_STAT *const sbuf) #ifdef S_ISLNK #if LINKS_READ_ONLY if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) - return aRONLY; + return FILE_ATTRIBUTE_READONLY; #endif #endif return 0; @@ -173,36 +173,36 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn, if (ro_opts == MAP_READONLY_YES) { /* Original Samba method - map inverse of user "w" bit. */ if ((smb_fname->st.st_ex_mode & S_IWUSR) == 0) { - result |= aRONLY; + result |= FILE_ATTRIBUTE_READONLY; } } else if (ro_opts == MAP_READONLY_PERMISSIONS) { /* Check actual permissions for read-only. */ if (!can_write_to_file(conn, smb_fname)) { - result |= aRONLY; + result |= FILE_ATTRIBUTE_READONLY; } } /* Else never set the readonly bit. */ if (MAP_ARCHIVE(conn) && ((smb_fname->st.st_ex_mode & S_IXUSR) != 0)) - result |= aARCH; + result |= FILE_ATTRIBUTE_ARCHIVE; if (MAP_SYSTEM(conn) && ((smb_fname->st.st_ex_mode & S_IXGRP) != 0)) - result |= aSYSTEM; + result |= FILE_ATTRIBUTE_SYSTEM; if (MAP_HIDDEN(conn) && ((smb_fname->st.st_ex_mode & S_IXOTH) != 0)) - result |= aHIDDEN; + result |= FILE_ATTRIBUTE_HIDDEN; if (S_ISDIR(smb_fname->st.st_ex_mode)) - result = aDIR | (result & aRONLY); + result = FILE_ATTRIBUTE_DIRECTORY | (result & FILE_ATTRIBUTE_READONLY); result |= set_link_read_only_flag(&smb_fname->st); DEBUG(8,("dos_mode_from_sbuf returning ")); - if (result & aHIDDEN) DEBUG(8, ("h")); - if (result & aRONLY ) DEBUG(8, ("r")); - if (result & aSYSTEM) DEBUG(8, ("s")); - if (result & aDIR ) DEBUG(8, ("d")); - if (result & aARCH ) DEBUG(8, ("a")); + if (result & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h")); + if (result & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r")); + if (result & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s")); + if (result & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d")); + if (result & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a")); DEBUG(8,("\n")); return result; @@ -318,18 +318,18 @@ static bool get_ea_dos_attribute(connection_struct *conn, } if (S_ISDIR(smb_fname->st.st_ex_mode)) { - dosattr |= aDIR; + dosattr |= FILE_ATTRIBUTE_DIRECTORY; } /* FILE_ATTRIBUTE_SPARSE is valid on get but not on set. */ *pattr = (uint32)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE)); DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr)); - if (dosattr & aHIDDEN) DEBUG(8, ("h")); - if (dosattr & aRONLY ) DEBUG(8, ("r")); - if (dosattr & aSYSTEM) DEBUG(8, ("s")); - if (dosattr & aDIR ) DEBUG(8, ("d")); - if (dosattr & aARCH ) DEBUG(8, ("a")); + if (dosattr & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h")); + if (dosattr & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r")); + if (dosattr & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s")); + if (dosattr & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d")); + if (dosattr & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a")); DEBUG(8,("\n")); @@ -465,7 +465,7 @@ uint32 dos_mode_msdfs(connection_struct *conn, /* Only . and .. are not hidden. */ if (p[0] == '.' && !((p[1] == '\0') || (p[1] == '.' && p[2] == '\0'))) { - result |= aHIDDEN; + result |= FILE_ATTRIBUTE_HIDDEN; } } @@ -473,9 +473,9 @@ uint32 dos_mode_msdfs(connection_struct *conn, /* Optimization : Only call is_hidden_path if it's not already hidden. */ - if (!(result & aHIDDEN) && + if (!(result & FILE_ATTRIBUTE_HIDDEN) && IS_HIDDEN_PATH(conn, smb_fname->base_name)) { - result |= aHIDDEN; + result |= FILE_ATTRIBUTE_HIDDEN; } if (result == 0) { @@ -486,11 +486,11 @@ uint32 dos_mode_msdfs(connection_struct *conn, DEBUG(8,("dos_mode_msdfs returning ")); - if (result & aHIDDEN) DEBUG(8, ("h")); - if (result & aRONLY ) DEBUG(8, ("r")); - if (result & aSYSTEM) DEBUG(8, ("s")); - if (result & aDIR ) DEBUG(8, ("d")); - if (result & aARCH ) DEBUG(8, ("a")); + if (result & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h")); + if (result & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r")); + if (result & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s")); + if (result & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d")); + if (result & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a")); if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]")); DEBUG(8,("\n")); @@ -507,13 +507,13 @@ int dos_attributes_to_stat_dos_flags(uint32_t dosmode) { uint32_t dos_stat_flags = 0; - if (dosmode & aARCH) + if (dosmode & FILE_ATTRIBUTE_ARCHIVE) dos_stat_flags |= UF_DOS_ARCHIVE; - if (dosmode & aHIDDEN) + if (dosmode & FILE_ATTRIBUTE_HIDDEN) dos_stat_flags |= UF_DOS_HIDDEN; - if (dosmode & aRONLY) + if (dosmode & FILE_ATTRIBUTE_READONLY) dos_stat_flags |= UF_DOS_RO; - if (dosmode & aSYSTEM) + if (dosmode & FILE_ATTRIBUTE_SYSTEM) dos_stat_flags |= UF_DOS_SYSTEM; if (dosmode & FILE_ATTRIBUTE_NONINDEXED) dos_stat_flags |= UF_DOS_NOINDEX; @@ -540,19 +540,19 @@ static bool get_stat_dos_flags(connection_struct *conn, smb_fname_str_dbg(smb_fname))); if (smb_fname->st.st_ex_flags & UF_DOS_ARCHIVE) - *dosmode |= aARCH; + *dosmode |= FILE_ATTRIBUTE_ARCHIVE; if (smb_fname->st.st_ex_flags & UF_DOS_HIDDEN) - *dosmode |= aHIDDEN; + *dosmode |= FILE_ATTRIBUTE_HIDDEN; if (smb_fname->st.st_ex_flags & UF_DOS_RO) - *dosmode |= aRONLY; + *dosmode |= FILE_ATTRIBUTE_READONLY; if (smb_fname->st.st_ex_flags & UF_DOS_SYSTEM) - *dosmode |= aSYSTEM; + *dosmode |= FILE_ATTRIBUTE_SYSTEM; if (smb_fname->st.st_ex_flags & UF_DOS_NOINDEX) *dosmode |= FILE_ATTRIBUTE_NONINDEXED; if (smb_fname->st.st_ex_flags & FILE_ATTRIBUTE_SPARSE) *dosmode |= FILE_ATTRIBUTE_SPARSE; if (S_ISDIR(smb_fname->st.st_ex_mode)) - *dosmode |= aDIR; + *dosmode |= FILE_ATTRIBUTE_DIRECTORY; *dosmode |= set_link_read_only_flag(&smb_fname->st); @@ -637,7 +637,7 @@ uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname) /* Only . and .. are not hidden. */ if (p[0] == '.' && !((p[1] == '\0') || (p[1] == '.' && p[2] == '\0'))) { - result |= aHIDDEN; + result |= FILE_ATTRIBUTE_HIDDEN; } } @@ -658,9 +658,9 @@ uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname) /* Optimization : Only call is_hidden_path if it's not already hidden. */ - if (!(result & aHIDDEN) && + if (!(result & FILE_ATTRIBUTE_HIDDEN) && IS_HIDDEN_PATH(conn, smb_fname->base_name)) { - result |= aHIDDEN; + result |= FILE_ATTRIBUTE_HIDDEN; } if (result == 0) { @@ -671,11 +671,11 @@ uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname) DEBUG(8,("dos_mode returning ")); - if (result & aHIDDEN) DEBUG(8, ("h")); - if (result & aRONLY ) DEBUG(8, ("r")); - if (result & aSYSTEM) DEBUG(8, ("s")); - if (result & aDIR ) DEBUG(8, ("d")); - if (result & aARCH ) DEBUG(8, ("a")); + if (result & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h")); + if (result & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r")); + if (result & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s")); + if (result & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d")); + if (result & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a")); if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]")); DEBUG(8,("\n")); @@ -712,9 +712,9 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, &smb_fname->st.st_ex_mode); if (S_ISDIR(smb_fname->st.st_ex_mode)) - dosmode |= aDIR; + dosmode |= FILE_ATTRIBUTE_DIRECTORY; else - dosmode &= ~aDIR; + dosmode &= ~FILE_ATTRIBUTE_DIRECTORY; new_create_timespec = smb_fname->st.st_ex_btime; diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 6655a6fb08..2fb4241968 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -21,9 +21,6 @@ #include "smbd/smbd.h" #include "smbd/globals.h" -/* From lib/error.c */ -extern struct unix_error_map unix_dos_nt_errmap[]; - bool use_nt_status(void) { return lp_nt_status_support() && (global_client_caps & CAP_STATUS32); @@ -80,11 +77,10 @@ void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatu smb_fn_name(CVAL(outbuf,smb_com)), nt_errstr(ntstatus))); } else { - /* We're returning a DOS error only. */ - if (NT_STATUS_IS_DOS(ntstatus)) { - eclass = NT_STATUS_DOS_CLASS(ntstatus); - ecode = NT_STATUS_DOS_CODE(ntstatus); - } else if (eclass == 0 && NT_STATUS_V(ntstatus)) { + /* We're returning a DOS error only, + * nt_status_to_dos() pulls DOS error codes out of the + * NTSTATUS */ + if (NT_STATUS_IS_DOS(ntstatus) || (eclass == 0 && NT_STATUS_V(ntstatus))) { ntstatus_to_dos(ntstatus, &eclass, &ecode); } diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index 960dcb703a..74855649ea 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -92,6 +92,11 @@ bool can_delete_file_in_directory(connection_struct *conn, return False; } + if (!lp_acl_check_permissions(SNUM(conn))) { + /* This option means don't check. */ + return true; + } + /* Get the parent directory permission mask and owners. */ if (!parent_dirname(ctx, smb_fname->base_name, &dname, NULL)) { return False; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 16d8853b54..3b317f9a86 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -240,8 +240,8 @@ void trigger_write_time_update(struct files_struct *fsp) /* trigger the update 2 seconds later */ fsp->update_write_time_event = - event_add_timed(smbd_event_context(), NULL, - timeval_current_ofs(0, delay), + event_add_timed(server_event_context(), NULL, + timeval_current_ofs_usec(delay), update_write_time_handler, fsp); } @@ -322,7 +322,7 @@ ssize_t write_file(struct smb_request *req, int dosmode = dos_mode(fsp->conn, fsp->fsp_name); if (!IS_DOS_ARCHIVE(dosmode)) { file_set_dosmode(fsp->conn, fsp->fsp_name, - dosmode | aARCH, NULL, false); + dosmode | FILE_ATTRIBUTE_ARCHIVE, NULL, false); } } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 08bc79dfd2..ec8d1139fa 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -163,11 +163,11 @@ static NTSTATUS check_parent_exists(TALLOC_CTX *ctx, * last compnent to shorten the tree walk. */ /* - * Safe to use CONST_DISCARD + * Safe to use discard_const_p * here as last_component points * into our smb_fname->base_name. */ - *pp_start = CONST_DISCARD(char *,last_component); + *pp_start = discard_const_p(char, last_component); /* Update dirpath. */ TALLOC_FREE(*pp_dirpath); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index b9063ccbb8..b8a25c1d5b 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -21,6 +21,8 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "libcli/security/security.h" +#include "util_tdb.h" +#include <ccan/hash/hash.h> #define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < real_max_open_files)) @@ -598,7 +600,6 @@ NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from, NTSTATUS file_name_hash(connection_struct *conn, const char *name, uint32_t *p_name_hash) { - TDB_DATA key; char *fullpath = NULL; /* Set the hash of the full pathname. */ @@ -609,8 +610,7 @@ NTSTATUS file_name_hash(connection_struct *conn, if (!fullpath) { return NT_STATUS_NO_MEMORY; } - key = string_term_tdb_data(fullpath); - *p_name_hash = tdb_jenkins_hash(&key); + *p_name_hash = hash(fullpath, strlen(fullpath) + 1, 0); DEBUG(10,("file_name_hash: %s hash 0x%x\n", fullpath, diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index 63c1f5dcb5..2736fa69d0 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -20,8 +20,10 @@ #include "includes.h" #include "smbd/smbd.h" #include "smbd/globals.h" +#include "lib/smbd_shim.h" #include "memcache.h" #include "messages.h" +#include "tdb_compat.h" #if defined(WITH_AIO) struct aio_extra *aio_list_head = NULL; @@ -144,14 +146,29 @@ struct memcache *smbd_memcache(void) return smbd_memcache_ctx; } +static const struct smbd_shim smbd_shim_fns = +{ + .cancel_pending_lock_requests_by_fid = smbd_cancel_pending_lock_requests_by_fid, + .send_stat_cache_delete_message = smbd_send_stat_cache_delete_message, + .can_delete_directory = smbd_can_delete_directory, + .change_to_root_user = smbd_change_to_root_user, + + .contend_level2_oplocks_begin = smbd_contend_level2_oplocks_begin, + .contend_level2_oplocks_end = smbd_contend_level2_oplocks_end, + + .become_root = smbd_become_root, + .unbecome_root = smbd_unbecome_root +}; void smbd_init_globals(void) { + set_smbd_shim(&smbd_shim_fns); + ZERO_STRUCT(conn_ctx_stack); ZERO_STRUCT(sec_ctx_stack); - smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection); + smbd_server_conn = talloc_zero(server_event_context(), struct smbd_server_connection); if (!smbd_server_conn) { exit_server("failed to create smbd_server_connection"); } @@ -159,3 +176,32 @@ void smbd_init_globals(void) smbd_server_conn->smb1.echo_handler.trusted_fd = -1; smbd_server_conn->smb1.echo_handler.socket_lock_fd = -1; } + +void smbd_set_server_fd(int fd) +{ + struct smbd_server_connection *sconn = smbd_server_conn; + char addr[INET6_ADDRSTRLEN]; + const char *name; + + sconn->sock = fd; + + /* + * Initialize sconn->client_id: If we can't find the client's + * name, default to its address. + */ + + client_addr(fd, sconn->client_id.addr, sizeof(sconn->client_id.addr)); + + name = client_name(sconn->sock); + if (strcmp(name, "UNKNOWN") != 0) { + name = talloc_strdup(sconn, name); + } else { + name = NULL; + } + sconn->client_id.name = + (name != NULL) ? name : sconn->client_id.addr; + + sub_set_socket_ids(sconn->client_id.addr, sconn->client_id.name, + client_socket_addr(sconn->sock, addr, + sizeof(addr))); +} diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 01be31a57f..97d75fd413 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -47,7 +47,8 @@ struct fsp_singleton_cache { extern const struct mangle_fns *mangle_fns; extern unsigned char *chartest; -extern TDB_CONTEXT *tdb_mangled_cache; +struct tdb_context; +extern struct tdb_context *tdb_mangled_cache; /* this determines how many characters are used from the original filename diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 4f2fea5265..669e28e715 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -28,6 +28,7 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "smbprofile.h" +#include "rpc_server/srv_pipe_hnd.h" #define NERR_notsupported 50 @@ -267,7 +268,7 @@ static void api_dcerpc_cmd(connection_struct *conn, struct smb_request *req, state->num_data = length; state->max_read = max_read; - subreq = np_write_send(state, smbd_event_context(), state->handle, + subreq = np_write_send(state, server_event_context(), state->handle, state->data, length); if (subreq == NULL) { TALLOC_FREE(state); @@ -297,14 +298,14 @@ static void api_dcerpc_cmd_write_done(struct tevent_req *subreq) goto send; } - state->data = TALLOC_REALLOC_ARRAY(state, state->data, uint8_t, + state->data = talloc_realloc(state, state->data, uint8_t, state->max_read); if (state->data == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); goto send; } - subreq = np_read_send(req->conn, smbd_event_context(), + subreq = np_read_send(req->conn, server_event_context(), state->handle, state->data, state->max_read); if (subreq == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); @@ -644,7 +645,7 @@ void reply_trans(struct smb_request *req) return; } - if ((state = TALLOC_P(conn, struct trans_state)) == NULL) { + if ((state = talloc(conn, struct trans_state)) == NULL) { DEBUG(0, ("talloc failed\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtrans); @@ -741,7 +742,7 @@ void reply_trans(struct smb_request *req) goto bad_param; } - if((state->setup = TALLOC_ARRAY( + if((state->setup = talloc_array( state, uint16, state->setup_count)) == NULL) { DEBUG(0,("reply_trans: setup malloc fail for %u " "bytes !\n", (unsigned int) @@ -807,7 +808,7 @@ void reply_transs(struct smb_request *req) START_PROFILE(SMBtranss); - show_msg((char *)req->inbuf); + show_msg((const char *)req->inbuf); if (req->wct < 8) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 13297c0222..dac91b2a40 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -34,17 +34,15 @@ #include "rpc_client/cli_spoolss.h" #include "rpc_client/init_spoolss.h" #include "../librpc/gen_ndr/ndr_srvsvc_c.h" -#include "../librpc/gen_ndr/srv_samr.h" -#include "../librpc/gen_ndr/srv_srvsvc.h" #include "../librpc/gen_ndr/rap.h" #include "../lib/util/binsearch.h" #include "../libcli/auth/libcli_auth.h" #include "rpc_client/init_lsa.h" -#include "rpc_server/rpc_ncacn_np.h" #include "../libcli/security/security.h" #include "printing.h" #include "passdb/machine_sid.h" #include "auth.h" +#include "rpc_server/rpc_ncacn_np.h" #ifdef CHECK_TYPES #undef CHECK_TYPES @@ -614,9 +612,9 @@ static void fill_printq_info_52(struct spoolss_DriverInfo3 *driver, { int i; fstring location; - trim_string((char *)driver->driver_path, "\\print$\\WIN40\\0\\", 0); - trim_string((char *)driver->data_file, "\\print$\\WIN40\\0\\", 0); - trim_string((char *)driver->help_file, "\\print$\\WIN40\\0\\", 0); + trim_string(discard_const_p(char, driver->driver_path), "\\print$\\WIN40\\0\\", 0); + trim_string(discard_const_p(char, driver->data_file), "\\print$\\WIN40\\0\\", 0); + trim_string(discard_const_p(char, driver->help_file), "\\print$\\WIN40\\0\\", 0); PACKI(desc, "W", 0x0400); /* don't know */ PACKS(desc, "z", driver->driver_name); /* long printer name */ @@ -643,7 +641,7 @@ static void fill_printq_info_52(struct spoolss_DriverInfo3 *driver, for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++) { - trim_string((char *)driver->dependent_files[i], "\\print$\\WIN40\\0\\", 0); + trim_string(discard_const_p(char, driver->dependent_files[i]), "\\print$\\WIN40\\0\\", 0); PACKS(desc,"z",driver->dependent_files[i]); /* driver files to copy */ DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i])); } @@ -1429,7 +1427,7 @@ static int fill_srv_info(struct srv_info_struct *service, static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) { - return StrCaseCmp(s1->name,s2->name); + return strcasecmp_m(s1->name,s2->name); } /**************************************************************************** @@ -1598,7 +1596,7 @@ static int srv_name_match(const char *n1, const char *n2) * the server will return a list of servers that exist on * the network greater than or equal to the FirstNameToReturn. */ - int ret = StrCaseCmp(n1, n2); + int ret = strcasecmp_m(n1, n2); if (ret <= 0) { return 0; @@ -1710,7 +1708,7 @@ static bool api_RNetServerEnum3(struct smbd_server_connection *sconn, */ for (;first > 0;) { int ret; - ret = StrCaseCmp(first_name, + ret = strcasecmp_m(first_name, servers[first-1].name); if (ret > 0) { break; @@ -2094,7 +2092,7 @@ static bool api_RNetShareEnum(struct smbd_server_connection *sconn, /* Ensure all the usershares are loaded. */ become_root(); load_registry_shares(); - count = load_usershare_shares(); + count = load_usershare_shares(sconn); unbecome_root(); data_len = fixed_len = string_len = 0; @@ -2256,7 +2254,7 @@ static bool api_RNetShareAdd(struct smbd_server_connection *sconn, return false; } - status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id, + status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc.syntax_id, conn->session_info, &conn->sconn->client_id, conn->sconn->msg_ctx, @@ -2367,7 +2365,7 @@ static bool api_RNetGroupEnum(struct smbd_server_connection *sconn, return False; } - status = rpc_pipe_open_internal( + status = rpc_pipe_open_interface( talloc_tos(), &ndr_table_samr.syntax_id, conn->session_info, &conn->sconn->client_id, conn->sconn->msg_ctx, &samr_pipe); @@ -2379,7 +2377,7 @@ static bool api_RNetGroupEnum(struct smbd_server_connection *sconn, b = samr_pipe->binding_handle; - status = dcerpc_samr_Connect2(b, talloc_tos(), global_myname(), + status = dcerpc_samr_Connect2(b, talloc_tos(), lp_netbios_name(), SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle, &result); if (!NT_STATUS_IS_OK(status)) { @@ -2573,7 +2571,7 @@ static bool api_NetUserGetGroups(struct smbd_server_connection *sconn, p = *rdata; endp = *rdata + *rdata_len; - status = rpc_pipe_open_internal( + status = rpc_pipe_open_interface( talloc_tos(), &ndr_table_samr.syntax_id, conn->session_info, &conn->sconn->client_id, conn->sconn->msg_ctx, &samr_pipe); @@ -2585,7 +2583,7 @@ static bool api_NetUserGetGroups(struct smbd_server_connection *sconn, b = samr_pipe->binding_handle; - status = dcerpc_samr_Connect2(b, talloc_tos(), global_myname(), + status = dcerpc_samr_Connect2(b, talloc_tos(), lp_netbios_name(), SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle, &result); if (!NT_STATUS_IS_OK(status)) { @@ -2765,7 +2763,7 @@ static bool api_RNetUserEnum(struct smbd_server_connection *sconn, p = *rdata; endp = *rdata + *rdata_len; - status = rpc_pipe_open_internal( + status = rpc_pipe_open_interface( talloc_tos(), &ndr_table_samr.syntax_id, conn->session_info, &conn->sconn->client_id, conn->sconn->msg_ctx, &samr_pipe); @@ -2777,7 +2775,7 @@ static bool api_RNetUserEnum(struct smbd_server_connection *sconn, b = samr_pipe->binding_handle; - status = dcerpc_samr_Connect2(b, talloc_tos(), global_myname(), + status = dcerpc_samr_Connect2(b, talloc_tos(), lp_netbios_name(), SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle, &result); if (!NT_STATUS_IS_OK(status)) { @@ -3031,7 +3029,7 @@ static bool api_SetUserPassword(struct smbd_server_connection *sconn, ZERO_STRUCT(domain_handle); ZERO_STRUCT(user_handle); - status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id, + status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id, conn->session_info, &conn->sconn->client_id, conn->sconn->msg_ctx, @@ -3046,7 +3044,7 @@ static bool api_SetUserPassword(struct smbd_server_connection *sconn, b = cli->binding_handle; status = dcerpc_samr_Connect2(b, mem_ctx, - global_myname(), + lp_netbios_name(), SAMR_ACCESS_CONNECT_TO_SERVER | SAMR_ACCESS_ENUM_DOMAINS | SAMR_ACCESS_LOOKUP_DOMAIN, @@ -3282,7 +3280,7 @@ static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn, memcpy(password.data, data, 516); memcpy(hash.hash, data+516, 16); - status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id, + status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id, conn->session_info, &conn->sconn->client_id, conn->sconn->msg_ctx, @@ -3296,7 +3294,7 @@ static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn, b = cli->binding_handle; - init_lsa_AsciiString(&server, global_myname()); + init_lsa_AsciiString(&server, lp_netbios_name()); init_lsa_AsciiString(&account, user); status = dcerpc_samr_OemChangePasswordUser2(b, mem_ctx, @@ -3866,7 +3864,7 @@ static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn, p = *rdata; p2 = p + struct_len; - status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id, + status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc.syntax_id, conn->session_info, &conn->sconn->client_id, conn->sconn->msg_ctx, @@ -4029,8 +4027,8 @@ static bool api_NetWkstaGetInfo(struct smbd_server_connection *sconn, } p += 4; - SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */ - SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */ + SCVAL(p,0,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION); /* system version - e.g 4 in 4.1 */ + SCVAL(p,1,SAMBA_MINOR_NBT_ANNOUNCE_VERSION); /* system version - e.g .1 in 4.1 */ p += 2; SIVAL(p,0,PTR_DIFF(p2,*rdata)); @@ -4293,7 +4291,7 @@ static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn, ZERO_STRUCT(domain_handle); ZERO_STRUCT(user_handle); - status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id, + status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id, conn->session_info, &conn->sconn->client_id, conn->sconn->msg_ctx, @@ -4308,7 +4306,7 @@ static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn, b = cli->binding_handle; status = dcerpc_samr_Connect2(b, mem_ctx, - global_myname(), + lp_netbios_name(), SAMR_ACCESS_CONNECT_TO_SERVER | SAMR_ACCESS_ENUM_DOMAINS | SAMR_ACCESS_LOOKUP_DOMAIN, diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index d98b350a37..c196a13ed0 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -25,6 +25,7 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "mangle.h" +#include "util_tdb.h" /* -------------------------------------------------------------------------- ** * Other stuff... @@ -86,7 +87,7 @@ static void init_valid_table(void) return; } - valid_table = (uint8 *)map_file(data_path("valid.dat"), 0x10000); + valid_table = (uint8 *)map_file(data_path(talloc_tos(), "valid.dat"), 0x10000); if (!valid_table) { smb_panic("Could not load valid.dat file required for mangle method=hash"); return; @@ -473,7 +474,7 @@ static void cache_mangled_name( const char mangled_name[13], return; /* Init the string lengths. */ - safe_strcpy(mangled_name_key, mangled_name, sizeof(mangled_name_key)-1); + strlcpy(mangled_name_key, mangled_name, sizeof(mangled_name_key)); /* See if the extensions are unmangled. If so, store the entry * without the extension, thus creating a "group" reverse map. @@ -638,7 +639,7 @@ static bool to_8_3(char magic_char, const char *in, char out[13], int default_ca if( p ) { if( p == s ) - safe_strcpy( extension, "___", 3 ); + strlcpy( extension, "___", 4); else { *p++ = 0; while( *p && extlen < 3 ) { @@ -670,7 +671,7 @@ static bool to_8_3(char magic_char, const char *in, char out[13], int default_ca if( *extension ) { out[baselen+3] = '.'; - safe_strcpy(&out[baselen+4], extension, 3); + strlcpy(&out[baselen+4], extension, 4); } SAFE_FREE(s); @@ -738,7 +739,7 @@ static bool hash_name_to_8_3(const char *in, if (NT_STATUS_IS_OK(is_valid_name(in_ucs2, False, False)) && NT_STATUS_IS_OK(is_8_3_w(in_ucs2, False))) { TALLOC_FREE(in_ucs2); - safe_strcpy(out, in, 12); + strlcpy(out, in, 13); return True; } @@ -772,8 +773,13 @@ const struct mangle_fns *mangle_hash_init(void) mangle_reset(); /* Create the in-memory tdb using our custom hash function. */ +#ifndef BUILD_TDB2 tdb_mangled_cache = tdb_open_ex("mangled_cache", 1031, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); +#else + /* FIXME: We should *never* open a tdb without logging! */ + tdb_mangled_cache = tdb_open("mangled_cache", TDB_INTERNAL, 0, 0, NULL); +#endif return &mangle_hash_fns; } diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index a39bb895c2..4de80cbe31 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -705,7 +705,7 @@ static bool hash2_name_to_8_3(const char *name, /* if the name is already a valid 8.3 name then we don't need to * change anything */ if (is_legal_name(name) && is_8_3(name, False, False, p)) { - safe_strcpy(new_name, name, 12); + strlcpy(new_name, name, 13); return True; } } diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 34997a13dc..63b08e1262 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -202,7 +202,7 @@ void reply_sendstrt(struct smb_request *req) TALLOC_FREE(smbd_msg_state); - smbd_msg_state = TALLOC_ZERO_P(NULL, struct msg_state); + smbd_msg_state = talloc_zero(NULL, struct msg_state); if (smbd_msg_state == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); @@ -259,7 +259,7 @@ void reply_sendtxt(struct smb_request *req) len = MIN(SVAL(msg, 0), smbreq_bufrem(req, msg+2)); - tmp = TALLOC_REALLOC_ARRAY(smbd_msg_state, smbd_msg_state->msg, + tmp = talloc_realloc(smbd_msg_state, smbd_msg_state->msg, char, old_len + len); if (tmp == NULL) { diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index ab67ac8596..47c2b1ee78 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -231,7 +231,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, char *oldcwd; const char *vfs_user; - conn = TALLOC_ZERO_P(ctx, connection_struct); + conn = talloc_zero(ctx, connection_struct); if (conn == NULL) { return NT_STATUS_NO_MEMORY; } @@ -252,7 +252,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, /* needed for smbd_vfs_init() */ - if (!(conn->params = TALLOC_ZERO_P(conn, struct share_params))) { + if (!(conn->params = talloc_zero(conn, struct share_params))) { DEBUG(0, ("TALLOC failed\n")); TALLOC_FREE(conn); return NT_STATUS_NO_MEMORY; @@ -364,7 +364,7 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, return False; } - alt_path = TALLOC_ARRAY(ctx, char *, MAX_REFERRAL_COUNT); + alt_path = talloc_array(ctx, char *, MAX_REFERRAL_COUNT); if (!alt_path) { return False; } @@ -378,7 +378,7 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, DEBUG(10,("parse_msdfs_symlink: count=%d\n", count)); if (count) { - reflist = *preflist = TALLOC_ZERO_ARRAY(ctx, + reflist = *preflist = talloc_zero_array(ctx, struct referral, count); if(reflist == NULL) { TALLOC_FREE(alt_path); @@ -443,7 +443,7 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx, if (pp_link_target) { bufsize = 1024; - link_target = TALLOC_ARRAY(ctx, char, bufsize); + link_target = talloc_array(ctx, char, bufsize); if (!link_target) { return False; } @@ -692,7 +692,7 @@ static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, bool *ppath_contains_wcard) { NTSTATUS status; - struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); + struct dfs_path *pdp = talloc(ctx, struct dfs_path); if (!pdp) { return NT_STATUS_NO_MEMORY; @@ -794,7 +794,7 @@ static NTSTATUS self_ref(TALLOC_CTX *ctx, *self_referralp = True; jucn->referral_count = 1; - if((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { + if((ref = talloc_zero(ctx, struct referral)) == NULL) { return NT_STATUS_NO_MEMORY; } @@ -825,7 +825,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, int snum; NTSTATUS status = NT_STATUS_NOT_FOUND; bool dummy; - struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); + struct dfs_path *pdp = talloc(ctx, struct dfs_path); char *oldpath; if (!pdp) { @@ -899,7 +899,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, */ jucn->referral_count = 1; - if ((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { + if ((ref = talloc_zero(ctx, struct referral)) == NULL) { TALLOC_FREE(pdp); return NT_STATUS_NO_MEMORY; } @@ -1233,7 +1233,7 @@ int setup_dfs_referral(connection_struct *orig_conn, pathnamep++; } - junction = TALLOC_ZERO_P(ctx, struct junction_map); + junction = talloc_zero(ctx, struct junction_map); if (!junction) { *pstatus = NT_STATUS_NO_MEMORY; talloc_destroy(ctx); @@ -1318,7 +1318,7 @@ bool create_junction(TALLOC_CTX *ctx, { int snum; bool dummy; - struct dfs_path *pdp = TALLOC_P(ctx,struct dfs_path); + struct dfs_path *pdp = talloc(ctx,struct dfs_path); NTSTATUS status; if (!pdp) { @@ -1630,7 +1630,7 @@ static int form_junctions(TALLOC_CTX *ctx, jucn[cnt].comment = ""; jucn[cnt].referral_count = 1; - ref = jucn[cnt].referral_list = TALLOC_ZERO_P(ctx, struct referral); + ref = jucn[cnt].referral_list = talloc_zero(ctx, struct referral); if (jucn[cnt].referral_list == NULL) { goto out; } @@ -1709,7 +1709,8 @@ out: return cnt; } -struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx, size_t *p_num_jn) +struct junction_map *enum_msdfs_links(struct smbd_server_connection *sconn, + TALLOC_CTX *ctx, size_t *p_num_jn) { struct junction_map *jn = NULL; int i=0; @@ -1724,7 +1725,7 @@ struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx, size_t *p_num_jn) /* Ensure all the usershares are loaded. */ become_root(); load_registry_shares(); - sharecount = load_usershare_shares(); + sharecount = load_usershare_shares(sconn); unbecome_root(); for(i=0;i < sharecount;i++) { @@ -1735,7 +1736,7 @@ struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx, size_t *p_num_jn) if (jn_count == 0) { return NULL; } - jn = TALLOC_ARRAY(ctx, struct junction_map, jn_count); + jn = talloc_array(ctx, struct junction_map, jn_count); if (!jn) { return NULL; } @@ -1786,7 +1787,7 @@ NTSTATUS resolve_dfspath_wcard(TALLOC_CTX *ctx, * Once srvstr_get_path() uses talloc it'll * be a talloced ptr anyway. */ - *pp_name_out = CONST_DISCARD(char *,name_in); + *pp_name_out = discard_const_p(char, name_in); } return status; } diff --git a/source3/smbd/msg_idmap.c b/source3/smbd/msg_idmap.c index b1ee60ff7f..2a00f1bbb9 100644 --- a/source3/smbd/msg_idmap.c +++ b/source3/smbd/msg_idmap.c @@ -27,10 +27,8 @@ #include "includes.h" #include "smbd/smbd.h" -#include "memcache.h" #include "globals.h" #include "../libcli/security/dom_sid.h" -#include "../librpc/gen_ndr/ndr_security.h" #include "idmap_cache.h" #include "passdb/lookup_sid.h" #include "auth.h" diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 6877ccc861..a6d7cc0ab3 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -224,7 +224,7 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn) } else { fstring myname; char *host_princ_s = NULL; - name_to_fqdn(myname, global_myname()); + name_to_fqdn(myname, lp_netbios_name()); strlower_m(myname); if (asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm()) == -1) { @@ -234,6 +234,10 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn) SAFE_FREE(host_princ_s); } + if (blob.length == 0 || blob.data == NULL) { + return data_blob_null; + } + blob_out = data_blob_talloc(ctx, NULL, 16 + blob.length); if (blob_out.data == NULL) { data_blob_free(&blob); @@ -242,10 +246,10 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn) memset(blob_out.data, '\0', 16); - checked_strlcpy(unix_name, global_myname(), sizeof(unix_name)); + checked_strlcpy(unix_name, lp_netbios_name(), sizeof(unix_name)); strlower_m(unix_name); push_ascii_nstring(dos_name, unix_name); - safe_strcpy((char *)blob_out.data, dos_name, 16); + strlcpy((char *)blob_out.data, dos_name, 17); #ifdef DEVELOPER /* Fix valgrind 'uninitialized bytes' issue. */ @@ -569,7 +573,7 @@ void reply_negprot(struct smb_request *req) char **tmp; - tmp = TALLOC_REALLOC_ARRAY(talloc_tos(), cliprotos, char *, + tmp = talloc_realloc(talloc_tos(), cliprotos, char *, num_cliprotos+1); if (tmp == NULL) { DEBUG(0, ("talloc failed\n")); @@ -712,6 +716,11 @@ void reply_negprot(struct smb_request *req) } TALLOC_FREE(cliprotos); + + if (lp_async_smb_echo_handler() && !fork_echo_handler(sconn)) { + exit_server("Failed to fork echo handler"); + } + END_PROFILE(SMBnegprot); return; } diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 24385c94a0..8160d5ac63 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -183,7 +183,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, SMB_ASSERT(fsp->notify == NULL); - if (!(fsp->notify = TALLOC_ZERO_P(NULL, struct notify_change_buf))) { + if (!(fsp->notify = talloc_zero(NULL, struct notify_change_buf))) { DEBUG(0, ("talloc failed\n")); return NT_STATUS_NO_MEMORY; } @@ -424,7 +424,7 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) return; } - if (!(changes = TALLOC_REALLOC_ARRAY( + if (!(changes = talloc_realloc( fsp->notify, fsp->notify->changes, struct notify_change, fsp->notify->num_changes+1))) { DEBUG(0, ("talloc_realloc failed\n")); @@ -520,7 +520,7 @@ struct sys_notify_context *sys_notify_context_create(connection_struct *conn, { struct sys_notify_context *ctx; - if (!(ctx = TALLOC_P(mem_ctx, struct sys_notify_context))) { + if (!(ctx = talloc(mem_ctx, struct sys_notify_context))) { DEBUG(0, ("talloc failed\n")); return NULL; } diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index a8eaf79392..a0193a4467 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -29,6 +29,8 @@ #include "dbwrap.h" #include "smbd/smbd.h" #include "messages.h" +#include "lib/util/tdb_wrap.h" +#include "util_tdb.h" struct notify_context { struct db_context *db_recursive; @@ -196,7 +198,7 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec notify->seqnum = seqnum; talloc_free(notify->array); - notify->array = TALLOC_ZERO_P(notify, struct notify_array); + notify->array = talloc_zero(notify, struct notify_array); NT_STATUS_HAVE_NO_MEMORY(notify->array); if (!rec) { @@ -529,7 +531,7 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0, depth = count_chars(e.path, '/'); - listel = TALLOC_ZERO_P(notify, struct notify_list); + listel = talloc_zero(notify, struct notify_list); if (listel == NULL) { status = NT_STATUS_NO_MEMORY; goto done; @@ -597,7 +599,7 @@ NTSTATUS notify_remove_onelevel(struct notify_context *notify, rec = notify->db_onelevel->fetch_locked( notify->db_onelevel, array, - make_tdb_data((uint8_t *)fid, sizeof(*fid))); + make_tdb_data((const uint8_t *)fid, sizeof(*fid))); if (rec == NULL) { DEBUG(10, ("notify_remove_onelevel: fetch_locked for %s failed" "\n", file_id_string_tos(fid))); @@ -841,7 +843,7 @@ void notify_onelevel(struct notify_context *notify, uint32_t action, if (notify->db_onelevel->fetch( notify->db_onelevel, array, make_tdb_data((uint8_t *)&fid, sizeof(fid)), - &dbuf) == -1) { + &dbuf) != 0) { TALLOC_FREE(array); return; } diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index d0056756ac..1f4fc2d0a2 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -22,6 +22,7 @@ #include "../lib/util/util_pw.h" #include "system/passwd.h" #include "passdb/lookup_sid.h" +#include "libsmb/libsmb.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_QUOTA @@ -200,14 +201,14 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) DEBUG(15,("quota entry for id[%s] path[%s]\n", sid_string_dbg(&sid), fsp->conn->connectpath)); - if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) { + if ((tmp_list_ent=talloc_zero(mem_ctx,SMB_NTQUOTA_LIST))==NULL) { DEBUG(0,("TALLOC_ZERO() failed\n")); *qt_list = NULL; talloc_destroy(mem_ctx); return (-1); } - if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) { + if ((tmp_list_ent->quotas=talloc_zero(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) { DEBUG(0,("TALLOC_ZERO() failed\n")); *qt_list = NULL; talloc_destroy(mem_ctx); @@ -240,7 +241,7 @@ void *init_quota_handle(TALLOC_CTX *mem_ctx) if (!mem_ctx) return False; - qt_handle = TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_HANDLE); + qt_handle = talloc_zero(mem_ctx,SMB_NTQUOTA_HANDLE); if (qt_handle==NULL) { DEBUG(0,("TALLOC_ZERO() failed\n")); return NULL; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 71f20ac77e..5fdb07d769 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -29,6 +29,7 @@ #include "auth.h" #include "ntioctl.h" #include "smbprofile.h" +#include "libsmb/libsmb.h" extern const struct generic_mapping file_generic_mapping; @@ -1363,7 +1364,7 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, /* Ensure attributes match. */ fattr = dos_mode(conn, smb_fname_src); - if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) { + if ((fattr & ~attrs) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) { status = NT_STATUS_NO_SUCH_FILE; goto out; } @@ -1450,7 +1451,7 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, status = close_file(NULL, fsp2, NORMAL_CLOSE); - /* Grrr. We have to do this as open_file_ntcreate adds aARCH when it + /* Grrr. We have to do this as open_file_ntcreate adds FILE_ATTRIBUTE_ARCHIVE when it creates the file. This isn't the correct thing to do in the copy case. JRA */ if (!parent_dirname(talloc_tos(), smb_fname_dst->base_name, &parent, @@ -2213,8 +2214,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, * Allocate the correct amount and return the pointer to let * it be deallocated when we return. */ - SHADOW_COPY_DATA *shadow_data = NULL; - TALLOC_CTX *shadow_mem_ctx = NULL; + struct shadow_copy_data *shadow_data = NULL; bool labels = False; uint32 labels_data_count = 0; uint32 i; @@ -2235,28 +2235,19 @@ static void call_nt_transact_ioctl(connection_struct *conn, labels = True; } - shadow_mem_ctx = talloc_init("SHADOW_COPY_DATA"); - if (shadow_mem_ctx == NULL) { - DEBUG(0,("talloc_init(SHADOW_COPY_DATA) failed!\n")); - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - shadow_data = TALLOC_ZERO_P(shadow_mem_ctx,SHADOW_COPY_DATA); + shadow_data = talloc_zero(talloc_tos(), + struct shadow_copy_data); if (shadow_data == NULL) { DEBUG(0,("TALLOC_ZERO() failed!\n")); - talloc_destroy(shadow_mem_ctx); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } - shadow_data->mem_ctx = shadow_mem_ctx; - /* * Call the VFS routine to actually do the work. */ if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) { - talloc_destroy(shadow_data->mem_ctx); + TALLOC_FREE(shadow_data); if (errno == ENOSYS) { DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n", conn->connectpath)); @@ -2281,14 +2272,14 @@ static void call_nt_transact_ioctl(connection_struct *conn, if (max_data_count<data_count) { DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n", max_data_count,data_count)); - talloc_destroy(shadow_data->mem_ctx); + TALLOC_FREE(shadow_data); reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); return; } pdata = nttrans_realloc(ppdata, data_count); if (pdata == NULL) { - talloc_destroy(shadow_data->mem_ctx); + TALLOC_FREE(shadow_data); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -2321,7 +2312,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, } } - talloc_destroy(shadow_data->mem_ctx); + TALLOC_FREE(shadow_data); send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, pdata, data_count); @@ -2861,7 +2852,7 @@ static void handle_nttrans(connection_struct *conn, { if (get_Protocol() >= PROTOCOL_NT1) { req->flags2 |= 0x40; /* IS_LONG_NAME */ - SSVAL(req->inbuf,smb_flg2,req->flags2); + SSVAL(discard_const_p(uint8_t, req->inbuf),smb_flg2,req->flags2); } @@ -3029,7 +3020,7 @@ void reply_nttrans(struct smb_request *req) return; } - if ((state = TALLOC_P(conn, struct trans_state)) == NULL) { + if ((state = talloc(conn, struct trans_state)) == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBnttrans); return; @@ -3203,7 +3194,7 @@ void reply_nttranss(struct smb_request *req) START_PROFILE(SMBnttranss); - show_msg((char *)req->inbuf); + show_msg((const char *)req->inbuf); if (req->wct < 18) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 14e6bf9b4e..86a5924f16 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -77,6 +77,16 @@ NTSTATUS smbd_check_open_rights(struct connection_struct *conn, NTSTATUS status; struct security_descriptor *sd = NULL; + if ((access_mask & DELETE_ACCESS) && !lp_acl_check_permissions(SNUM(conn))) { + *access_granted = access_mask; + + DEBUG(10,("smbd_check_open_rights: not checking ACL " + "on DELETE_ACCESS on file %s. Granting 0x%x\n", + smb_fname_str_dbg(smb_fname), + (unsigned int)*access_granted )); + return NT_STATUS_OK; + } + status = SMB_VFS_GET_NT_ACL(conn, smb_fname->base_name, (SECINFO_OWNER | SECINFO_GROUP | @@ -241,6 +251,8 @@ void change_file_owner_to_parent(connection_struct *conn, DEBUG(10,("change_file_owner_to_parent: changed new file %s to " "parent directory uid %u.\n", fsp_str_dbg(fsp), (unsigned int)smb_fname_parent->st.st_ex_uid)); + /* Ensure the uid entry is updated. */ + fsp->fsp_name->st.st_ex_uid = smb_fname_parent->st.st_ex_uid; } TALLOC_FREE(smb_fname_parent); @@ -316,10 +328,9 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn, /* Ensure we're pointing at the same place. */ if (smb_fname_cwd->st.st_ex_dev != psbuf->st_ex_dev || - smb_fname_cwd->st.st_ex_ino != psbuf->st_ex_ino || - smb_fname_cwd->st.st_ex_mode != psbuf->st_ex_mode ) { + smb_fname_cwd->st.st_ex_ino != psbuf->st_ex_ino) { DEBUG(0,("change_dir_owner_to_parent: " - "device/inode/mode on directory %s changed. " + "device/inode on directory %s changed. " "Refusing to chown !\n", fname )); status = NT_STATUS_ACCESS_DENIED; goto chdir; @@ -350,6 +361,8 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn, DEBUG(10,("change_dir_owner_to_parent: changed ownership of new " "directory %s to parent directory uid %u.\n", fname, (unsigned int)smb_fname_parent->st.st_ex_uid )); + /* Ensure the uid entry is updated. */ + psbuf->st_ex_uid = smb_fname_parent->st.st_ex_uid; } chdir: @@ -378,6 +391,7 @@ static NTSTATUS open_file(files_struct *fsp, int accmode = (flags & O_ACCMODE); int local_flags = flags; bool file_existed = VALID_STAT(fsp->fsp_name->st); + bool file_created = false; fsp->fh->fd = -1; errno = EPERM; @@ -477,23 +491,7 @@ static NTSTATUS open_file(files_struct *fsp, } if ((local_flags & O_CREAT) && !file_existed) { - - /* Inherit the ACL if required */ - if (lp_inherit_perms(SNUM(conn))) { - inherit_access_posix_acl(conn, parent_dir, - smb_fname->base_name, - unx_mode); - } - - /* Change the owner if required. */ - if (lp_inherit_owner(SNUM(conn))) { - change_file_owner_to_parent(conn, parent_dir, - fsp); - } - - notify_fname(conn, NOTIFY_ACTION_ADDED, - FILE_NOTIFY_CHANGE_FILE_NAME, - smb_fname->base_name); + file_created = true; } } else { @@ -603,6 +601,47 @@ static NTSTATUS open_file(files_struct *fsp, fd_close(fsp); return status; } + + if (file_created) { + bool need_re_stat = false; + /* Do all inheritance work after we've + done a successful stat call and filled + in the stat struct in fsp->fsp_name. */ + + /* Inherit the ACL if required */ + if (lp_inherit_perms(SNUM(conn))) { + inherit_access_posix_acl(conn, parent_dir, + smb_fname->base_name, + unx_mode); + need_re_stat = true; + } + + /* Change the owner if required. */ + if (lp_inherit_owner(SNUM(conn))) { + change_file_owner_to_parent(conn, parent_dir, + fsp); + need_re_stat = true; + } + + if (need_re_stat) { + if (fsp->fh->fd == -1) { + ret = SMB_VFS_STAT(conn, smb_fname); + } else { + ret = SMB_VFS_FSTAT(fsp, &smb_fname->st); + /* If we have an fd, this stat should succeed. */ + if (ret == -1) { + DEBUG(0,("Error doing fstat on open file %s " + "(%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno) )); + } + } + } + + notify_fname(conn, NOTIFY_ACTION_ADDED, + FILE_NOTIFY_CHANGE_FILE_NAME, + smb_fname->base_name); + } } /* @@ -949,7 +988,9 @@ static NTSTATUS send_break_message(files_struct *fsp, * Do internal consistency checks on the share mode for a file. */ -static void find_oplock_types(struct share_mode_lock *lck, +static void find_oplock_types(files_struct *fsp, + int oplock_request, + struct share_mode_lock *lck, struct share_mode_entry **pp_batch, struct share_mode_entry **pp_ex_or_batch, bool *got_level2, @@ -962,11 +1003,27 @@ static void find_oplock_types(struct share_mode_lock *lck, *got_level2 = false; *got_no_oplock = false; + /* Ignore stat or internal opens, as is done in + delay_for_batch_oplocks() and + delay_for_exclusive_oplocks(). + */ + if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) { + return; + } + for (i=0; i<lck->num_share_modes; i++) { if (!is_valid_share_mode_entry(&lck->share_modes[i])) { continue; } + if (lck->share_modes[i].op_type == NO_OPLOCK && + is_stat_open(lck->share_modes[i].access_mask)) { + /* We ignore stat opens in the table - they + always have NO_OPLOCK and never get or + cause breaks. JRA. */ + continue; + } + if (BATCH_OPLOCK_TYPE(lck->share_modes[i].op_type)) { /* batch - can only be one. */ if (*pp_ex_or_batch || *pp_batch || *got_level2 || *got_no_oplock) { @@ -1037,18 +1094,8 @@ static bool delay_for_exclusive_oplocks(files_struct *fsp, return false; } -static bool file_has_brlocks(files_struct *fsp) -{ - struct byte_range_lock *br_lck; - - br_lck = brl_get_locks_readonly(fsp); - if (!br_lck) - return false; - - return br_lck->num_locks > 0 ? true : false; -} - static void grant_fsp_oplock_type(files_struct *fsp, + const struct byte_range_lock *br_lck, int oplock_request, bool got_level2_oplock, bool got_a_none_oplock) @@ -1066,7 +1113,7 @@ static void grant_fsp_oplock_type(files_struct *fsp, DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n", fsp->oplock_type, fsp_str_dbg(fsp))); return; - } else if (lp_locking(fsp->conn->params) && file_has_brlocks(fsp)) { + } else if (br_lck && br_lck->num_locks > 0) { DEBUG(10,("grant_fsp_oplock_type: file %s has byte range locks\n", fsp_str_dbg(fsp))); fsp->oplock_type = NO_OPLOCK; @@ -1544,6 +1591,55 @@ void remove_deferred_open_entry(struct file_id id, uint64_t mid, } } +/**************************************************************** + Ensure we get the brlock lock followed by the share mode lock + in the correct order to prevent deadlocks if other smbd's are + using the brlock database on this file simultaneously with this open + (that code also gets the locks in brlock -> share mode lock order). +****************************************************************/ + +static bool acquire_ordered_locks(TALLOC_CTX *mem_ctx, + files_struct *fsp, + const struct file_id id, + const char *connectpath, + const struct smb_filename *smb_fname, + const struct timespec *p_old_write_time, + struct share_mode_lock **p_lck, + struct byte_range_lock **p_br_lck) +{ + /* Ordering - we must get the br_lck for this + file before the share mode. */ + if (lp_locking(fsp->conn->params)) { + *p_br_lck = brl_get_locks_readonly(fsp); + if (*p_br_lck == NULL) { + DEBUG(0, ("Could not get br_lock\n")); + return false; + } + /* Note - we don't need to free the returned + br_lck explicitly as it was allocated on talloc_tos() + and so will be autofreed (and release the lock) + once the frame context disappears. + + If it was set to fsp->brlock_rec then it was + talloc_move'd to hang off the fsp pointer and + in this case is guarenteed to not be holding the + lock on the brlock database. */ + } + + *p_lck = get_share_mode_lock(mem_ctx, + id, + connectpath, + smb_fname, + p_old_write_time); + + if (*p_lck == NULL) { + DEBUG(0, ("Could not get share mode lock\n")); + TALLOC_FREE(*p_br_lck); + return false; + } + return true; +} + /**************************************************************************** Open a file with a share mode. Passed in an already created files_struct *. ****************************************************************************/ @@ -1622,9 +1718,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, unx_mode = (mode_t)(new_dos_attributes & ~FILE_FLAG_POSIX_SEMANTICS); new_dos_attributes = 0; } else { - /* We add aARCH to this as this mode is only used if the file is + /* We add FILE_ATTRIBUTE_ARCHIVE to this as this mode is only used if the file is * created new. */ - unx_mode = unix_mode(conn, new_dos_attributes | aARCH, + unx_mode = unix_mode(conn, new_dos_attributes | FILE_ATTRIBUTE_ARCHIVE, smb_fname, parent_dir); } @@ -1888,6 +1984,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, } if (file_existed) { + struct byte_range_lock *br_lck = NULL; struct share_mode_entry *batch_entry = NULL; struct share_mode_entry *exclusive_entry = NULL; bool got_level2_oplock = false; @@ -1896,17 +1993,21 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, struct timespec old_write_time = smb_fname->st.st_ex_mtime; id = vfs_file_id_from_sbuf(conn, &smb_fname->st); - lck = get_share_mode_lock(talloc_tos(), id, - conn->connectpath, - smb_fname, &old_write_time); - - if (lck == NULL) { - DEBUG(0, ("Could not get share mode lock\n")); + if (!acquire_ordered_locks(talloc_tos(), + fsp, + id, + conn->connectpath, + smb_fname, + &old_write_time, + &lck, + &br_lck)) { return NT_STATUS_SHARING_VIOLATION; } /* Get the types we need to examine. */ - find_oplock_types(lck, + find_oplock_types(fsp, + oplock_request, + lck, &batch_entry, &exclusive_entry, &got_level2_oplock, @@ -1953,6 +2054,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, } grant_fsp_oplock_type(fsp, + br_lck, oplock_request, got_level2_oplock, got_a_none_oplock); @@ -2109,13 +2211,12 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, open_access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { - if (lck != NULL) { - TALLOC_FREE(lck); - } + TALLOC_FREE(lck); return fsp_open; } if (!file_existed) { + struct byte_range_lock *br_lck = NULL; struct share_mode_entry *batch_entry = NULL; struct share_mode_entry *exclusive_entry = NULL; bool got_level2_oplock = false; @@ -2138,20 +2239,21 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, id = fsp->file_id; - lck = get_share_mode_lock(talloc_tos(), id, - conn->connectpath, - smb_fname, &old_write_time); - - if (lck == NULL) { - DEBUG(0, ("open_file_ntcreate: Could not get share " - "mode lock for %s\n", - smb_fname_str_dbg(smb_fname))); - fd_close(fsp); + if (!acquire_ordered_locks(talloc_tos(), + fsp, + id, + conn->connectpath, + smb_fname, + &old_write_time, + &lck, + &br_lck)) { return NT_STATUS_SHARING_VIOLATION; } /* Get the types we need to examine. */ - find_oplock_types(lck, + find_oplock_types(fsp, + oplock_request, + lck, &batch_entry, &exclusive_entry, &got_level2_oplock, @@ -2194,8 +2296,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, if (!NT_STATUS_IS_OK(status)) { struct deferred_open_record state; - fd_close(fsp); - state.delayed_for_oplocks = False; state.id = id; @@ -2211,10 +2311,12 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, req, &state); } TALLOC_FREE(lck); + fd_close(fsp); return status; } grant_fsp_oplock_type(fsp, + br_lck, oplock_request, got_level2_oplock, got_a_none_oplock); @@ -2335,7 +2437,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, new_file_created = True; } - set_share_mode(lck, fsp, get_current_uid(conn), 0, + set_share_mode(lck, fsp, get_current_uid(conn), + req ? req->mid : 0, fsp->oplock_type); /* Handle strange delete on close create semantics. */ @@ -2361,7 +2464,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, lp_store_dos_attributes(SNUM(conn))) { if (!posix_open) { if (file_set_dosmode(conn, smb_fname, - new_dos_attributes | aARCH, + new_dos_attributes | FILE_ATTRIBUTE_ARCHIVE, parent_dir, true) == 0) { unx_mode = smb_fname->st.st_ex_mode; } @@ -2475,6 +2578,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, char *parent_dir; NTSTATUS status; bool posix_open = false; + bool need_re_stat = false; if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share " @@ -2496,7 +2600,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, posix_open = true; mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS); } else { - mode = unix_mode(conn, aDIR, smb_dname, parent_dir); + mode = unix_mode(conn, FILE_ATTRIBUTE_DIRECTORY, smb_dname, parent_dir); } if (SMB_VFS_MKDIR(conn, smb_dname->base_name, mode) != 0) { @@ -2521,7 +2625,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, if (lp_store_dos_attributes(SNUM(conn))) { if (!posix_open) { file_set_dosmode(conn, smb_dname, - file_attributes | aDIR, + file_attributes | FILE_ATTRIBUTE_DIRECTORY, parent_dir, true); } } @@ -2529,6 +2633,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, if (lp_inherit_perms(SNUM(conn))) { inherit_access_posix_acl(conn, parent_dir, smb_dname->base_name, mode); + need_re_stat = true; } if (!posix_open) { @@ -2543,6 +2648,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, SMB_VFS_CHMOD(conn, smb_dname->base_name, (smb_dname->st.st_ex_mode | (mode & ~smb_dname->st.st_ex_mode))); + need_re_stat = true; } } @@ -2551,6 +2657,15 @@ static NTSTATUS mkdir_internal(connection_struct *conn, change_dir_owner_to_parent(conn, parent_dir, smb_dname->base_name, &smb_dname->st); + need_re_stat = true; + } + + if (need_re_stat) { + if (SMB_VFS_LSTAT(conn, smb_dname) == -1) { + DEBUG(2, ("Could not stat directory '%s' just created: %s\n", + smb_fname_str_dbg(smb_dname), strerror(errno))); + return map_nt_error_from_unix(errno); + } } notify_fname(conn, NOTIFY_ACTION_ADDED, FILE_NOTIFY_CHANGE_DIR_NAME, @@ -2828,7 +2943,8 @@ static NTSTATUS open_directory(connection_struct *conn, return status; } - set_share_mode(lck, fsp, get_current_uid(conn), 0, NO_OPLOCK); + set_share_mode(lck, fsp, get_current_uid(conn), + req ? req->mid : 0, NO_OPLOCK); /* For directories the delete on close bit at open time seems always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ @@ -3018,7 +3134,7 @@ NTSTATUS open_streams_for_delete(connection_struct *conn, return NT_STATUS_OK; } - streams = TALLOC_ARRAY(talloc_tos(), files_struct *, num_streams); + streams = talloc_array(talloc_tos(), files_struct *, num_streams); if (streams == NULL) { DEBUG(0, ("talloc failed\n")); status = NT_STATUS_NO_MEMORY; @@ -3172,8 +3288,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn, /* Setting FILE_SHARE_DELETE is the hint. */ - if (lp_acl_check_permissions(SNUM(conn)) - && (create_disposition != FILE_CREATE) + if ((create_disposition != FILE_CREATE) && (access_mask & DELETE_ACCESS) && (!(can_delete_file_in_directory(conn, smb_fname) || can_access_file_acl(conn, smb_fname, DELETE_ACCESS)))) { @@ -3531,7 +3646,7 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn, * Copy in the base directory name. */ - parent_fname = TALLOC_ARRAY(talloc_tos(), char, + parent_fname = talloc_array(talloc_tos(), char, dir_name_len+2); if (parent_fname == NULL) { status = NT_STATUS_NO_MEMORY; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 087d6ef045..284b0321aa 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -224,7 +224,7 @@ bool should_notify_deferred_opens() static char *new_break_message_smb1(TALLOC_CTX *mem_ctx, files_struct *fsp, int cmd) { - char *result = TALLOC_ARRAY(mem_ctx, char, smb_size + 8*2 + 0); + char *result = talloc_array(mem_ctx, char, smb_size + 8*2 + 0); if (result == NULL) { DEBUG(0, ("talloc failed\n")); @@ -353,7 +353,7 @@ static void add_oplock_timeout_handler(files_struct *fsp) } fsp->oplock_timeout = - event_add_timed(smbd_event_context(), fsp, + event_add_timed(server_event_context(), fsp, timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0), oplock_timeout_handler, fsp); @@ -459,7 +459,7 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx message_to_share_mode_entry(&msg, (char *)data->data); DEBUG(10, ("Got oplock async level 2 break message from pid %s: " - "%s/%lu\n", procid_str(talloc_tos(), &src), + "%s/%lu\n", server_id_str(talloc_tos(), &src), file_id_string_tos(&msg.id), msg.share_file_id)); fsp = initial_break_processing(sconn, msg.id, msg.share_file_id); @@ -510,7 +510,7 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, message_to_share_mode_entry(&msg, (char *)data->data); DEBUG(10, ("Got oplock break message from pid %s: %s/%lu\n", - procid_str(talloc_tos(), &src), file_id_string_tos(&msg.id), + server_id_str(talloc_tos(), &src), file_id_string_tos(&msg.id), msg.share_file_id)); fsp = initial_break_processing(sconn, msg.id, msg.share_file_id); @@ -617,7 +617,7 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, file_id = (unsigned long)IVAL(data->data, 24); DEBUG(10, ("Got kernel oplock break message from pid %s: %s/%u\n", - procid_str(talloc_tos(), &src), file_id_string_tos(&id), + server_id_str(talloc_tos(), &src), file_id_string_tos(&id), (unsigned int)file_id)); fsp = initial_break_processing(sconn, id, file_id); @@ -704,7 +704,7 @@ static void process_oplock_break_response(struct messaging_context *msg_ctx, message_to_share_mode_entry(&msg, (char *)data->data); DEBUG(10, ("Got oplock break response from pid %s: %s/%lu mid %llu\n", - procid_str(talloc_tos(), &src), file_id_string_tos(&msg.id), + server_id_str(talloc_tos(), &src), file_id_string_tos(&msg.id), msg.share_file_id, (unsigned long long)msg.op_mid)); schedule_deferred_open_message_smb(msg.op_mid); @@ -732,7 +732,7 @@ static void process_open_retry_message(struct messaging_context *msg_ctx, message_to_share_mode_entry(&msg, (char *)data->data); DEBUG(10, ("Got open retry msg from pid %s: %s mid %llu\n", - procid_str(talloc_tos(), &src), file_id_string_tos(&msg.id), + server_id_str(talloc_tos(), &src), file_id_string_tos(&msg.id), (unsigned long long)msg.op_mid)); schedule_deferred_open_message_smb(msg.op_mid); @@ -849,7 +849,7 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp, TALLOC_FREE(lck); } -void contend_level2_oplocks_begin(files_struct *fsp, +void smbd_contend_level2_oplocks_begin(files_struct *fsp, enum level2_contention_type type) { if (koplocks && koplocks->ops->contend_level2_oplocks_begin) { @@ -860,7 +860,7 @@ void contend_level2_oplocks_begin(files_struct *fsp, contend_level2_oplocks_begin_default(fsp, type); } -void contend_level2_oplocks_end(files_struct *fsp, +void smbd_contend_level2_oplocks_end(files_struct *fsp, enum level2_contention_type type) { /* Only kernel oplocks implement this so far */ diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 207952d040..ef737efd22 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -332,7 +332,7 @@ struct kernel_oplocks *irix_init_kernel_oplocks(TALLOC_CTX *mem_ctx) ctx->read_fd = pfd[0]; ctx->write_fd = pfd[1]; - ctx->read_fde = event_add_fd(smbd_event_context(), + ctx->read_fde = event_add_fd(server_event_context(), ctx, ctx->read_fd, EVENT_FD_READ, diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 4f243e2e9f..19f4d6e06d 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -210,7 +210,7 @@ struct kernel_oplocks *linux_init_kernel_oplocks(TALLOC_CTX *mem_ctx) ctx->ops = &linux_koplocks; - se = tevent_add_signal(smbd_event_context(), + se = tevent_add_signal(server_event_context(), ctx, RT_SIGNAL_LEASE, SA_SIGINFO, linux_oplock_signal_handler, diff --git a/source3/smbd/oplock_onefs.c b/source3/smbd/oplock_onefs.c index dbf465ca63..4717b1faf7 100644 --- a/source3/smbd/oplock_onefs.c +++ b/source3/smbd/oplock_onefs.c @@ -709,7 +709,7 @@ struct kernel_oplocks *onefs_init_kernel_oplocks(TALLOC_CTX *mem_ctx) DEBUG(10, ("oplock event_fd = %d\n", ctx->onefs_event_fd)); /* Register the oplock event_fd with samba's event system */ - ctx->read_fde = event_add_fd(smbd_event_context(), + ctx->read_fde = event_add_fd(server_event_context(), ctx, ctx->onefs_event_fd, EVENT_FD_READ, diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 720b1bf4c2..69b37596c5 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -549,7 +549,7 @@ static char *validate_group(struct smbd_server_connection *sconn, DEBUG(10,("validate_group: = gr_mem = " "%s\n", gptr->gr_mem[i])); - safe_strcpy(member, gptr->gr_mem[i], + strlcpy(member, gptr->gr_mem[i], list_len - (member-member_list)); member += member_len; } @@ -644,7 +644,7 @@ bool authorise_login(struct smbd_server_connection *sconn, get_session_workgroup(sconn), user2,password)) { ok = True; - fstrcpy(user,user2); + strlcpy(user,user2,sizeof(fstring)); DEBUG(3,("authorise_login: ACCEPTED: session " "list username (%s) and given " "password ok\n", user)); @@ -695,7 +695,7 @@ bool authorise_login(struct smbd_server_connection *sconn, get_session_workgroup(sconn), user2,password)) { ok = True; - fstrcpy(user,user2); + strlcpy(user,user2,sizeof(fstring)); DEBUG(3,("authorise_login: ACCEPTED: " "user list username and " "given password ok (%s)\n", @@ -714,7 +714,7 @@ bool authorise_login(struct smbd_server_connection *sconn, fstrcpy(guestname,lp_guestaccount()); guest_pw = Get_Pwnam_alloc(talloc_tos(), guestname); if (guest_pw != NULL) { - fstrcpy(user,guestname); + strlcpy(user,guestname,sizeof(fstring)); ok = True; DEBUG(3,("authorise_login: ACCEPTED: guest account " "and guest ok (%s)\n", user)); diff --git a/source3/smbd/perfcount.c b/source3/smbd/perfcount.c index 3bc83b98d5..1561893758 100644 --- a/source3/smbd/perfcount.c +++ b/source3/smbd/perfcount.c @@ -85,7 +85,7 @@ NTSTATUS smb_register_perfcounter(int interface_version, const char *name, entry = SMB_XMALLOC_P(struct smb_perfcount_module); entry->name = smb_xstrdup(name); - entry->handlers = (struct smb_perfcount_handlers*) handlers; + entry->handlers = discard_const_p(struct smb_perfcount_handlers, handlers); DLIST_ADD(modules, entry); DEBUG(3, ("Successfully added perfcounter module '%s'\n", name)); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 89d6c8dfca..2de48adcbc 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -29,6 +29,7 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "libcli/security/security.h" +#include "rpc_server/srv_pipe_hnd.h" #define PIPE "\\PIPE\\" #define PIPELEN strlen(PIPE) @@ -202,7 +203,7 @@ void reply_pipe_write(struct smb_request *req) DEBUG(6, ("reply_pipe_write: %x name: %s len: %d\n", (int)fsp->fnum, fsp_str_dbg(fsp), (int)state->numtowrite)); - subreq = np_write_send(state, smbd_event_context(), + subreq = np_write_send(state, server_event_context(), fsp->fake_file_handle, data, state->numtowrite); if (subreq == NULL) { TALLOC_FREE(state); @@ -269,7 +270,7 @@ void reply_pipe_write_and_X(struct smb_request *req) { files_struct *fsp = file_fsp(req, SVAL(req->vwv+2, 0)); int smb_doff = SVAL(req->vwv+11, 0); - uint8_t *data; + const uint8_t *data; struct pipe_write_andx_state *state; struct tevent_req *subreq; @@ -298,7 +299,7 @@ void reply_pipe_write_and_X(struct smb_request *req) DEBUG(6, ("reply_pipe_write_and_X: %x name: %s len: %d\n", (int)fsp->fnum, fsp_str_dbg(fsp), (int)state->numtowrite)); - data = (uint8_t *)smb_base(req->inbuf) + smb_doff; + data = (const uint8_t *)smb_base(req->inbuf) + smb_doff; if (state->pipe_start_message_raw) { /* @@ -318,7 +319,7 @@ void reply_pipe_write_and_X(struct smb_request *req) state->numtowrite -= 2; } - subreq = np_write_send(state, smbd_event_context(), + subreq = np_write_send(state, server_event_context(), fsp->fake_file_handle, data, state->numtowrite); if (subreq == NULL) { TALLOC_FREE(state); @@ -425,7 +426,7 @@ void reply_pipe_read_and_X(struct smb_request *req) state->outbuf = req->outbuf; req->outbuf = NULL; - subreq = np_read_send(state, smbd_event_context(), + subreq = np_read_send(state, server_event_context(), fsp->fake_file_handle, data, state->smb_maxcnt); if (subreq == NULL) { diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 9252ee639f..da25a52b8d 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3687,7 +3687,7 @@ NTSTATUS append_parent_acl(files_struct *fsp, num_aces += parent_sd->dacl->num_aces; - if((new_ace = TALLOC_ZERO_ARRAY(mem_ctx, struct security_ace, + if((new_ace = talloc_zero_array(mem_ctx, struct security_ace, num_aces)) == NULL) { return NT_STATUS_NO_MEMORY; } @@ -4744,13 +4744,13 @@ struct security_descriptor *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fna struct fd_handle fh; NTSTATUS status; - conn = TALLOC_ZERO_P(ctx, connection_struct); + conn = talloc_zero(ctx, connection_struct); if (conn == NULL) { DEBUG(0, ("talloc failed\n")); return NULL; } - if (!(conn->params = TALLOC_P(conn, struct share_params))) { + if (!(conn->params = talloc(conn, struct share_params))) { DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n")); TALLOC_FREE(conn); return NULL; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 248b3e403d..f3f532fbae 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "../lib/tsocket/tsocket.h" #include "system/filesys.h" #include "smbd/smbd.h" #include "smbd/globals.h" @@ -32,6 +33,8 @@ #include "auth.h" #include "messages.h" #include "smbprofile.h" +#include "rpc_server/spoolss/srv_spoolss_nt.h" +#include "libsmb/libsmb.h" extern bool global_machine_password_needs_changing; @@ -318,7 +321,7 @@ static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, /* Copy the header we've written. */ - *buffer = (char *)TALLOC_MEMDUP(mem_ctx, + *buffer = (char *)talloc_memdup(mem_ctx, writeX_header, sizeof(writeX_header)); @@ -343,7 +346,7 @@ static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, * talloc and return. */ - *buffer = TALLOC_ARRAY(mem_ctx, char, len+4); + *buffer = talloc_array(mem_ctx, char, len+4); if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", @@ -412,7 +415,7 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, * The +4 here can't wrap, we've checked the length above already. */ - *buffer = TALLOC_ARRAY(mem_ctx, char, len+4); + *buffer = talloc_array(mem_ctx, char, len+4); if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", @@ -501,9 +504,9 @@ static bool init_smb_request(struct smb_request *req, req->vuid = SVAL(inbuf, smb_uid); req->tid = SVAL(inbuf, smb_tid); req->wct = CVAL(inbuf, smb_wct); - req->vwv = (uint16_t *)(inbuf+smb_vwv); + req->vwv = discard_const_p(uint16_t, (inbuf+smb_vwv)); req->buflen = smb_buflen(inbuf); - req->buf = (const uint8_t *)smb_buf(inbuf); + req->buf = (const uint8_t *)smb_buf_const(inbuf); req->unread_bytes = unread_bytes; req->encrypted = encrypted; req->sconn = sconn; @@ -522,7 +525,7 @@ static bool init_smb_request(struct smb_request *req, return false; } /* Ensure bcc is correct. */ - if (((uint8 *)smb_buf(inbuf)) + req->buflen > inbuf + req_size) { + if (((const uint8_t *)smb_buf_const(inbuf)) + req->buflen > inbuf + req_size) { DEBUG(0,("init_smb_request: invalid bcc number %u " "(wct = %u, size %u)\n", (unsigned int)req->buflen, @@ -591,7 +594,7 @@ static bool push_queued_message(struct smb_request *req, int msg_len = smb_len(req->inbuf) + 4; struct pending_message_list *msg; - msg = TALLOC_ZERO_P(NULL, struct pending_message_list); + msg = talloc_zero(NULL, struct pending_message_list); if(msg == NULL) { DEBUG(0,("push_message: malloc fail (1)\n")); @@ -621,7 +624,7 @@ static bool push_queued_message(struct smb_request *req, } } - msg->te = event_add_timed(smbd_event_context(), + msg->te = event_add_timed(server_event_context(), msg, end_time, smbd_deferred_open_timer, @@ -705,7 +708,7 @@ void schedule_deferred_open_message_smb(uint64_t mid) "scheduling mid %llu\n", (unsigned long long)mid )); - te = event_add_timed(smbd_event_context(), + te = event_add_timed(server_event_context(), pml, timeval_zero(), smbd_deferred_open_timer, @@ -888,7 +891,7 @@ struct idle_event *event_add_idle(struct event_context *event_ctx, struct idle_event *result; struct timeval now = timeval_current(); - result = TALLOC_P(mem_ctx, struct idle_event); + result = talloc(mem_ctx, struct idle_event); if (result == NULL) { DEBUG(0, ("talloc failed\n")); return NULL; @@ -931,8 +934,8 @@ void smbd_setup_sig_term_handler(void) { struct tevent_signal *se; - se = tevent_add_signal(smbd_event_context(), - smbd_event_context(), + se = tevent_add_signal(server_event_context(), + server_event_context(), SIGTERM, 0, smbd_sig_term_handler, NULL); @@ -984,11 +987,11 @@ static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection * * select for longer than it would take to wait for them. */ - event_add_to_poll_args(smbd_event_context(), conn, + event_add_to_poll_args(server_event_context(), conn, &conn->pfds, &num_pfds, &timeout); /* Process a signal and timed events now... */ - if (run_events_poll(smbd_event_context(), 0, NULL, 0)) { + if (run_events_poll(server_event_context(), 0, NULL, 0)) { return NT_STATUS_RETRY; } @@ -1003,11 +1006,14 @@ static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection * errno = sav; } - if (ret == -1 && errno != EINTR) { + if (ret == -1) { + if (errno == EINTR) { + return NT_STATUS_RETRY; + } return map_nt_error_from_unix(errno); } - retry = run_events_poll(smbd_event_context(), ret, conn->pfds, + retry = run_events_poll(server_event_context(), ret, conn->pfds, num_pfds); if (retry) { return NT_STATUS_RETRY; @@ -1345,12 +1351,12 @@ static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req, char *msg; if (asprintf(&msg, "num_bytes too large: %u", (unsigned)num_bytes) == -1) { - msg = CONST_DISCARD(char *, "num_bytes too large"); + msg = discard_const_p(char, "num_bytes too large"); } smb_panic(msg); } - *outbuf = TALLOC_ARRAY(mem_ctx, char, + *outbuf = talloc_array(mem_ctx, char, smb_size + num_words*2 + num_bytes); if (*outbuf == NULL) { return false; @@ -1372,7 +1378,7 @@ static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req, void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes) { char *outbuf; - if (!create_outbuf(req, req, (char *)req->inbuf, &outbuf, num_words, + if (!create_outbuf(req, req, (const char *)req->inbuf, &outbuf, num_words, num_bytes)) { smb_panic("could not allocate output buffer\n"); } @@ -1444,7 +1450,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in if (smb_messages[type].fn == NULL) { DEBUG(0,("Unknown message type %d!\n",type)); - smb_dump("Unknown", 1, (char *)req->inbuf, size); + smb_dump("Unknown", 1, (const char *)req->inbuf, size); reply_unknown_new(req, type); return NULL; } @@ -1459,10 +1465,10 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type), (int)sys_getpid(), (unsigned long)conn)); - smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size); + smb_dump(smb_fn_name(type), 1, (const char *)req->inbuf, size); /* Ensure this value is replaced in the incoming packet. */ - SSVAL(req->inbuf,smb_uid,session_tag); + SSVAL(discard_const_p(uint8_t, req->inbuf),smb_uid,session_tag); /* * Ensure the correct username is in current_user_info. This is a @@ -1748,7 +1754,7 @@ static void construct_reply_common(struct smb_request *req, const char *inbuf, void construct_reply_common_req(struct smb_request *req, char *outbuf) { - construct_reply_common(req, (char *)req->inbuf, outbuf); + construct_reply_common(req, (const char *)req->inbuf, outbuf); } /* @@ -1888,7 +1894,7 @@ static bool smb_splice_chain(uint8_t **poutbuf, uint8_t smb_command, return false; } - outbuf = TALLOC_REALLOC_ARRAY(NULL, *poutbuf, uint8_t, new_size); + outbuf = talloc_realloc(NULL, *poutbuf, uint8_t, new_size); if (outbuf == NULL) { DEBUG(0, ("talloc failed\n")); return false; @@ -1902,7 +1908,7 @@ static bool smb_splice_chain(uint8_t **poutbuf, uint8_t smb_command, if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) { DEBUG(1, ("invalid command chain\n")); - *poutbuf = TALLOC_REALLOC_ARRAY( + *poutbuf = talloc_realloc( NULL, *poutbuf, uint8_t, old_size); return false; } @@ -1971,9 +1977,9 @@ void chain_reply(struct smb_request *req) uint32_t chain_offset; /* uint32_t to avoid overflow */ uint8_t wct; - uint16_t *vwv; + const uint16_t *vwv; uint16_t buflen; - uint8_t *buf; + const uint8_t *buf; if (IVAL(req->outbuf, smb_rcls) != 0) { fixup_chain_error_packet(req); @@ -1990,7 +1996,7 @@ void chain_reply(struct smb_request *req) if ((req->wct < 2) || (CVAL(req->outbuf, smb_wct) < 2)) { if (req->chain_outbuf == NULL) { - req->chain_outbuf = TALLOC_REALLOC_ARRAY( + req->chain_outbuf = talloc_realloc( req, req->outbuf, uint8_t, smb_len(req->outbuf) + 4); if (req->chain_outbuf == NULL) { @@ -2022,7 +2028,7 @@ void chain_reply(struct smb_request *req) * over-allocated (reply_pipe_read_and_X used to be such an * example). */ - req->chain_outbuf = TALLOC_REALLOC_ARRAY( + req->chain_outbuf = talloc_realloc( req, req->outbuf, uint8_t, smb_len(req->outbuf) + 4); if (req->chain_outbuf == NULL) { smb_panic("talloc failed"); @@ -2122,7 +2128,7 @@ void chain_reply(struct smb_request *req) if (length_needed > smblen) { goto error; } - vwv = (uint16_t *)(smb_base(req->inbuf) + chain_offset + 1); + vwv = (const uint16_t *)(smb_base(req->inbuf) + chain_offset + 1); /* * Now grab the new byte buffer.... @@ -2138,11 +2144,11 @@ void chain_reply(struct smb_request *req) if (length_needed > smblen) { goto error; } - buf = (uint8_t *)(vwv+wct+1); + buf = (const uint8_t *)(vwv+wct+1); req->cmd = chain_cmd; req->wct = wct; - req->vwv = vwv; + req->vwv = discard_const_p(uint16_t, vwv); req->buflen = buflen; req->buf = buf; @@ -2240,13 +2246,14 @@ static bool fd_is_readable(int fd) } -static void smbd_server_connection_write_handler(struct smbd_server_connection *conn) +static void smbd_server_connection_write_handler( + struct smbd_server_connection *sconn) { /* TODO: make write nonblocking */ } static void smbd_server_connection_read_handler( - struct smbd_server_connection *conn, int fd) + struct smbd_server_connection *sconn, int fd) { uint8_t *inbuf = NULL; size_t inbuf_len = 0; @@ -2256,29 +2263,29 @@ static void smbd_server_connection_read_handler( NTSTATUS status; uint32_t seqnum; - bool from_client = (conn->sock == fd); + bool from_client = (sconn->sock == fd); if (from_client) { - smbd_lock_socket(conn); + smbd_lock_socket(sconn); if (lp_async_smb_echo_handler() && !fd_is_readable(fd)) { DEBUG(10,("the echo listener was faster\n")); - smbd_unlock_socket(conn); + smbd_unlock_socket(sconn); return; } /* TODO: make this completely nonblocking */ - status = receive_smb_talloc(mem_ctx, conn, fd, + status = receive_smb_talloc(mem_ctx, sconn, fd, (char **)(void *)&inbuf, 0, /* timeout */ &unread_bytes, &encrypted, &inbuf_len, &seqnum, false /* trusted channel */); - smbd_unlock_socket(conn); + smbd_unlock_socket(sconn); } else { /* TODO: make this completely nonblocking */ - status = receive_smb_talloc(mem_ctx, conn, fd, + status = receive_smb_talloc(mem_ctx, sconn, fd, (char **)(void *)&inbuf, 0, /* timeout */ &unread_bytes, @@ -2298,7 +2305,7 @@ static void smbd_server_connection_read_handler( } process: - process_smb(conn, inbuf, inbuf_len, unread_bytes, + process_smb(sconn, inbuf, inbuf_len, unread_bytes, seqnum, encrypted, NULL); } @@ -2339,6 +2346,7 @@ static void smbd_server_echo_handler(struct event_context *ev, } } +#ifdef CLUSTER_SUPPORT /**************************************************************************** received when we should release a specific IP ****************************************************************************/ @@ -2351,6 +2359,9 @@ static void release_ip(const char *ip, void *priv) p = addr + 7; } + DEBUG(10, ("Got release IP message for %s, " + "our address is %s\n", ip, p)); + if ((strcmp(p, ip) == 0) || ((p != addr) && strcmp(addr, ip) == 0)) { /* we can't afford to do a clean exit - that involves database writes, which would potentially mean we @@ -2365,16 +2376,6 @@ static void release_ip(const char *ip, void *priv) } } -static void msg_release_ip(struct messaging_context *msg_ctx, void *private_data, - uint32_t msg_type, struct server_id server_id, DATA_BLOB *data) -{ - struct smbd_server_connection *sconn = talloc_get_type_abort( - private_data, struct smbd_server_connection); - - release_ip((char *)data->data, sconn->client_id.addr); -} - -#ifdef CLUSTER_SUPPORT static int client_get_tcp_info(int sock, struct sockaddr_storage *server, struct sockaddr_storage *client) { @@ -2608,7 +2609,7 @@ static bool smbd_echo_reply(uint8_t *inbuf, size_t inbuf_len, return false; } - if (!create_outbuf(talloc_tos(), &req, (char *)req.inbuf, &outbuf, + if (!create_outbuf(talloc_tos(), &req, (const char *)req.inbuf, &outbuf, 1, req.buflen)) { DEBUG(10, ("create_outbuf failed\n")); return false; @@ -2788,7 +2789,7 @@ static void smbd_echo_loop(struct smbd_server_connection *sconn, /* * Handle SMBecho requests in a forked child process */ -static bool fork_echo_handler(struct smbd_server_connection *sconn) +bool fork_echo_handler(struct smbd_server_connection *sconn) { int listener_pipe[2]; int res; @@ -2813,7 +2814,7 @@ static bool fork_echo_handler(struct smbd_server_connection *sconn) set_blocking(listener_pipe[1], false); status = reinit_after_fork(sconn->msg_ctx, - smbd_event_context(), + server_event_context(), procid_self(), false); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("reinit_after_fork failed: %s\n", @@ -2833,7 +2834,7 @@ static bool fork_echo_handler(struct smbd_server_connection *sconn) * Without smb signing this is the same as the normal smbd * listener. This needs to change once signing comes in. */ - sconn->smb1.echo_handler.trusted_fde = event_add_fd(smbd_event_context(), + sconn->smb1.echo_handler.trusted_fde = event_add_fd(server_event_context(), sconn, sconn->smb1.echo_handler.trusted_fd, EVENT_FD_READ, @@ -2902,8 +2903,7 @@ void smbd_process(struct smbd_server_connection *sconn) const char *remaddr = NULL; int ret; - if (lp_maxprotocol() == PROTOCOL_SMB2 && - !lp_async_smb_echo_handler()) { + if (lp_maxprotocol() == PROTOCOL_SMB2) { /* * We're not making the decision here, * we're just allowing the client @@ -3024,10 +3024,6 @@ void smbd_process(struct smbd_server_connection *sconn) exit_server("Failed to init smb_signing"); } - if (lp_async_smb_echo_handler() && !fork_echo_handler(sconn)) { - exit_server("Failed to fork echo handler"); - } - /* Setup oplocks */ if (!init_oplocks(sconn->msg_ctx)) exit_server("Failed to init oplocks"); @@ -3035,8 +3031,6 @@ void smbd_process(struct smbd_server_connection *sconn) /* register our message handlers */ messaging_register(sconn->msg_ctx, NULL, MSG_SMB_FORCE_TDIS, msg_force_tdis); - messaging_register(sconn->msg_ctx, sconn, - MSG_SMB_RELEASE_IP, msg_release_ip); messaging_register(sconn->msg_ctx, NULL, MSG_SMB_CLOSE_FILE, msg_close_file); @@ -3050,7 +3044,7 @@ void smbd_process(struct smbd_server_connection *sconn) MSG_DEBUG, debug_message); if ((lp_keepalive() != 0) - && !(event_add_idle(smbd_event_context(), NULL, + && !(event_add_idle(server_event_context(), NULL, timeval_set(lp_keepalive(), 0), "keepalive", keepalive_fn, NULL))) { @@ -3058,14 +3052,14 @@ void smbd_process(struct smbd_server_connection *sconn) exit(1); } - if (!(event_add_idle(smbd_event_context(), NULL, + if (!(event_add_idle(server_event_context(), NULL, timeval_set(IDLE_CLOSED_TIMEOUT, 0), "deadtime", deadtime_fn, sconn))) { DEBUG(0, ("Could not add deadtime event\n")); exit(1); } - if (!(event_add_idle(smbd_event_context(), NULL, + if (!(event_add_idle(server_event_context(), NULL, timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0), "housekeeping", housekeeping_fn, sconn))) { DEBUG(0, ("Could not add housekeeping event\n")); @@ -3122,7 +3116,7 @@ void smbd_process(struct smbd_server_connection *sconn) exit_server("init_dptrs() failed"); } - sconn->smb1.fde = event_add_fd(smbd_event_context(), + sconn->smb1.fde = event_add_fd(server_event_context(), sconn, sconn->sock, EVENT_FD_READ, @@ -3157,7 +3151,7 @@ void smbd_process(struct smbd_server_connection *sconn) bool req_is_in_chain(struct smb_request *req) { - if (req->vwv != (uint16_t *)(req->inbuf+smb_vwv)) { + if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) { /* * We're right now handling a subsequent request, so we must * be in a chain diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 36eea5e16e..adeaf68899 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -1,3 +1,50 @@ +/* + * Unix SMB/CIFS implementation. + * Main SMB server routines + * + * Copyright (C) Andrew Tridgell 1992-2002,2006 + * Copyright (C) Jeremy Allison 1992-2010 + * Copyright (C) Volker Lendecke 1993-2009 + * Copyright (C) John H Terpstra 1995-1998 + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998 + * Copyright (C) Paul Ashton 1997-1998 + * Copyright (C) Tim Potter 1999-2000 + * Copyright (C) T.D.Lee@durham.ac.uk 1999 + * Copyright (C) Ying Chen 2000 + * Copyright (C) Shirish Kalele 2000 + * Copyright (C) Andrew Bartlett 2001-2003 + * Copyright (C) Alexander Bokovoy 2002,2005 + * Copyright (C) Simo Sorce 2001-2002,2009 + * Copyright (C) Andreas Gruenbacher 2002 + * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002 + * Copyright (C) Martin Pool 2002 + * Copyright (C) Luke Howard 2003 + * Copyright (C) Stefan (metze) Metzmacher 2003,2009 + * Copyright (C) Steve French 2005 + * Copyright (C) Gerald (Jerry) Carter 2006 + * Copyright (C) James Peach 2006-2007 + * Copyright (C) Jelmer Vernooij 2002-2003 + * Copyright (C) Michael Adam 2007 + * Copyright (C) Rishi Srivatsavai 2007 + * Copyright (C) Tim Prouty 2009 + * Copyright (C) Gregor Beck 2011 + * + * 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/>. + */ + +#ifndef _SMBD_PROTO_H_ +#define _SMBD_PROTO_H_ /* The following definitions come from smbd/signing.c */ @@ -23,7 +70,7 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn, size_t smb_maxcnt); NTSTATUS schedule_aio_write_and_X(connection_struct *conn, struct smb_request *req, - files_struct *fsp, char *data, + files_struct *fsp, const char *data, SMB_OFF_T startpos, size_t numtowrite); NTSTATUS schedule_smb2_aio_read(connection_struct *conn, @@ -63,6 +110,9 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, uint64_t offset, uint64_t count, uint64_t blocking_smblctx); +void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp, + struct byte_range_lock *br_lck, + enum file_close_type close_type); void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck, enum file_close_type close_type); @@ -94,7 +144,7 @@ NTSTATUS delete_all_streams(connection_struct *conn, const char *fname); void conn_init(struct smbd_server_connection *sconn); int conn_num_open(struct smbd_server_connection *sconn); -bool conn_snum_used(int snum); +bool conn_snum_used(struct smbd_server_connection *sconn, int snum); connection_struct *conn_find(struct smbd_server_connection *sconn, unsigned cnum); connection_struct *conn_new(struct smbd_server_connection *sconn); @@ -102,6 +152,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, @@ -188,6 +239,8 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset); bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset); NTSTATUS can_delete_directory(struct connection_struct *conn, const char *dirname); +NTSTATUS smbd_can_delete_directory(struct connection_struct *conn, + const char *dirname); /* The following definitions come from smbd/dmapi.c */ @@ -407,7 +460,8 @@ bool create_junction(TALLOC_CTX *ctx, struct junction_map *jucn); bool create_msdfs_link(const struct junction_map *jucn); bool remove_msdfs_link(const struct junction_map *jucn); -struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx, size_t *p_num_jn); +struct junction_map *enum_msdfs_links(struct smbd_server_connection *sconn, + TALLOC_CTX *ctx, size_t *p_num_jn); NTSTATUS resolve_dfspath(TALLOC_CTX *ctx, connection_struct *conn, bool dfs_pathnames, @@ -621,6 +675,10 @@ void contend_level2_oplocks_begin(files_struct *fsp, enum level2_contention_type type); void contend_level2_oplocks_end(files_struct *fsp, enum level2_contention_type type); +void smbd_contend_level2_oplocks_begin(files_struct *fsp, + enum level2_contention_type type); +void smbd_contend_level2_oplocks_end(files_struct *fsp, + enum level2_contention_type type); void share_mode_entry_to_message(char *msg, const struct share_mode_entry *e); void message_to_share_mode_entry(struct share_mode_entry *e, char *msg); bool init_oplocks(struct messaging_context *msg_ctx); @@ -750,6 +808,7 @@ size_t req_wct_ofs(struct smb_request *req); void chain_reply(struct smb_request *req); bool req_is_in_chain(struct smb_request *req); void smbd_process(struct smbd_server_connection *sconn); +bool fork_echo_handler(struct smbd_server_connection *sconn); /* The following definitions come from smbd/quotas.c */ @@ -996,10 +1055,18 @@ bool stat_cache_lookup(connection_struct *conn, char **pp_dirpath, char **pp_start, SMB_STRUCT_STAT *pst); +void smbd_send_stat_cache_delete_message(struct messaging_context *msg_ctx, + const char *name); void send_stat_cache_delete_message(struct messaging_context *msg_ctx, const char *name); void stat_cache_delete(const char *name); -unsigned int fast_string_hash(TDB_DATA *key); +#if BUILD_TDB2 +struct tdb_data; +unsigned int fast_string_hash(struct tdb_data *key); +#else +struct TDB_DATA; +unsigned int fast_string_hash(struct TDB_DATA *key); +#endif bool reset_stat_cache( void ); /* The following definitions come from smbd/statvfs.c */ @@ -1046,15 +1113,17 @@ 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); bool change_to_root_user(void); -bool become_authenticated_pipe_user(struct pipes_struct *p); +bool smbd_change_to_root_user(void); +bool become_authenticated_pipe_user(struct auth_serversupplied_info *session_info); bool unbecome_authenticated_pipe_user(void); void become_root(void); void unbecome_root(void); +void smbd_become_root(void); +void smbd_unbecome_root(void); bool become_user(connection_struct *conn, uint16 vuid); bool become_user_by_session(connection_struct *conn, const struct auth_serversupplied_info *session_info); @@ -1130,3 +1199,5 @@ void *avahi_start_register(TALLOC_CTX *mem_ctx, struct tevent_context *ev, /* The following definitions come from smbd/msg_idmap.c */ void msg_idmap_register_msgs(struct messaging_context *ctx); + +#endif /* _SMBD_PROTO_H_ */ diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index c9f85b6ad0..41516621f0 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -26,6 +26,7 @@ #include "includes.h" #include "smbd/smbd.h" +#include "system/filesys.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_QUOTA diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 01d4332b7e..a804884ef7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -314,7 +314,7 @@ size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req, char **pp_dest, const char *src, int flags, NTSTATUS *err, bool *contains_wcard) { - return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2, + return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2, pp_dest, src, smbreq_bufrem(req, src), flags, err, contains_wcard); } @@ -491,6 +491,13 @@ static bool netbios_session_retarget(struct smbd_server_connection *sconn, return ret; } +static void reply_called_name_not_present(char *outbuf) +{ + smb_setlen(outbuf, 1); + SCVAL(outbuf, 0, 0x83); + SCVAL(outbuf, 4, 0x82); +} + /**************************************************************************** Reply to a (netbios-level) special message. ****************************************************************************/ @@ -531,11 +538,13 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4); if (name_len1 <= 0 || name_len1 > inbuf_size - 4) { DEBUG(0,("Invalid name length in session request\n")); + reply_called_name_not_present(outbuf); break; } name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1); if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) { DEBUG(0,("Invalid name length in session request\n")); + reply_called_name_not_present(outbuf); break; } @@ -546,6 +555,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb if (name_type1 == -1 || name_type2 == -1) { DEBUG(0,("Invalid name type in session request\n")); + reply_called_name_not_present(outbuf); break; } @@ -575,7 +585,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb if (name_type2 == 'R') { /* We are being asked for a pathworks session --- no thanks! */ - SCVAL(outbuf, 0,0x83); + reply_called_name_not_present(outbuf); break; } @@ -614,6 +624,10 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb msg_type, msg_flags)); srv_send_smb(sconn, outbuf, false, 0, false, NULL); + + if (CVAL(outbuf, 0) != 0x82) { + exit_server_cleanly("invalid netbios session"); + } return; } @@ -873,7 +887,7 @@ void reply_tcon_and_X(struct smb_request *req) service)); /* set the incoming and outgoing tid to the just created one */ - SSVAL(req->inbuf,smb_tid,conn->cnum); + SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum); SSVAL(req->outbuf,smb_tid,conn->cnum); END_PROFILE(SMBtconX); @@ -958,7 +972,7 @@ void reply_ioctl(struct smb_request *req) SSVAL(p, 0, 0); } srvstr_push((char *)req->outbuf, req->flags2, p+2, - global_myname(), 15, + lp_netbios_name(), 15, STR_TERMINATE|STR_ASCII); if (conn) { srvstr_push((char *)req->outbuf, req->flags2, @@ -1108,9 +1122,9 @@ void reply_getatr(struct smb_request *req) /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ if (*fname == '\0') { - mode = aHIDDEN | aDIR; + mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY; if (!CAN_WRITE(conn)) { - mode |= aRONLY; + mode |= FILE_ATTRIBUTE_READONLY; } size = 0; mtime = 0; @@ -1156,7 +1170,7 @@ void reply_getatr(struct smb_request *req) } mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime); - if (mode & aDIR) { + if (mode & FILE_ATTRIBUTE_DIRECTORY) { size = 0; } } @@ -1257,9 +1271,9 @@ void reply_setatr(struct smb_request *req) if (mode != FILE_ATTRIBUTE_NORMAL) { if (VALID_STAT_OF_DIR(smb_fname->st)) - mode |= aDIR; + mode |= FILE_ATTRIBUTE_DIRECTORY; else - mode &= ~aDIR; + mode &= ~FILE_ATTRIBUTE_DIRECTORY; if (file_set_dosmode(conn, smb_fname, mode, NULL, false) != 0) { @@ -1428,7 +1442,7 @@ void reply_search(struct smb_request *req) status_len = SVAL(p, 0); p += 2; - /* dirtype &= ~aDIR; */ + /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */ if (status_len == 0) { nt_status = filename_convert(ctx, conn, @@ -1520,11 +1534,11 @@ void reply_search(struct smb_request *req) /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */ dptr_init_search_op(dirptr); - if ((dirtype&0x1F) == aVOLID) { + if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) { char buf[DIR_STRUCT_SIZE]; memcpy(buf,status,21); if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)), - 0,aVOLID,0,!allow_long_path_components)) { + 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) { reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; } @@ -1820,7 +1834,7 @@ void reply_open(struct smb_request *req) mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime); - if (fattr & aDIR) { + if (fattr & FILE_ATTRIBUTE_DIRECTORY) { DEBUG(3,("attempt to open a directory %s\n", fsp_str_dbg(fsp))); close_file(req, fsp, ERROR_CLOSE); @@ -2004,7 +2018,7 @@ void reply_open_and_X(struct smb_request *req) fattr = dos_mode(conn, fsp->fsp_name); mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime); - if (fattr & aDIR) { + if (fattr & FILE_ATTRIBUTE_DIRECTORY) { close_file(req, fsp, ERROR_CLOSE); reply_nterror(req, NT_STATUS_ACCESS_DENIED); goto out; @@ -2160,7 +2174,7 @@ void reply_mknew(struct smb_request *req) goto out; } - if (fattr & aVOLID) { + if (fattr & FILE_ATTRIBUTE_VOLUME) { DEBUG(0,("Attempt to create file (%s) with volid set - " "please report this\n", smb_fname_str_dbg(smb_fname))); @@ -2381,15 +2395,18 @@ void reply_ctemp(struct smb_request *req) static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, uint16 dirtype) { - uint32 fmode; - if (!CAN_WRITE(conn)) { return NT_STATUS_MEDIA_WRITE_PROTECTED; } - fmode = dos_mode(conn, fsp->fsp_name); - if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) { - return NT_STATUS_NO_SUCH_FILE; + if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != + (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) { + /* Only bother to read the DOS attribute if we might deny the + rename on the grounds of attribute missmatch. */ + uint32_t fmode = dos_mode(conn, fsp->fsp_name); + if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) { + return NT_STATUS_NO_SUCH_FILE; + } } if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) { @@ -2449,16 +2466,16 @@ static NTSTATUS do_unlink(connection_struct *conn, fattr = dos_mode(conn, smb_fname); if (dirtype & FILE_ATTRIBUTE_NORMAL) { - dirtype = aDIR|aARCH|aRONLY; + dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY; } - dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM); + dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM); if (!dirtype) { return NT_STATUS_NO_SUCH_FILE; } if (!dir_check_ftype(conn, fattr, dirtype)) { - if (fattr & aDIR) { + if (fattr & FILE_ATTRIBUTE_DIRECTORY) { return NT_STATUS_FILE_IS_A_DIRECTORY; } return NT_STATUS_NO_SUCH_FILE; @@ -2489,13 +2506,13 @@ static NTSTATUS do_unlink(connection_struct *conn, } /* Can't delete a directory. */ - if (fattr & aDIR) { + if (fattr & FILE_ATTRIBUTE_DIRECTORY) { return NT_STATUS_FILE_IS_A_DIRECTORY; } #endif #if 0 /* JRATEST */ - else if (dirtype & aDIR) /* Asked for a directory and it isn't. */ + else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */ return NT_STATUS_OBJECT_NAME_INVALID; #endif /* JRATEST */ @@ -2632,7 +2649,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, const char *dname = NULL; char *talloced = NULL; - if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) { + if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) { status = NT_STATUS_OBJECT_NAME_INVALID; goto out; } @@ -3077,9 +3094,9 @@ static void send_file_readbraw(connection_struct *conn, normal_readbraw: - outbuf = TALLOC_ARRAY(NULL, char, nread+4); + outbuf = talloc_array(NULL, char, nread+4); if (!outbuf) { - DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n", + DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n", (unsigned)(nread+4))); reply_readbraw_error(sconn); return; @@ -3213,7 +3230,7 @@ void reply_readbraw(struct smb_request *req) "(%x << 32) used and we don't support " "64 bit offsets.\n", (unsigned int)IVAL(req->vwv+8, 0) )); - reply_readbraw_error(); + reply_readbraw_error(sconn); END_PROFILE(SMBreadbraw); return; } @@ -3896,7 +3913,7 @@ void reply_writebraw(struct smb_request *req) size_t numtowrite=0; size_t tcount; SMB_OFF_T startpos; - char *data=NULL; + const char *data=NULL; bool write_through; files_struct *fsp; struct lock_struct lock; @@ -3909,7 +3926,7 @@ void reply_writebraw(struct smb_request *req) * type of SMBwritec, not SMBwriteBraw, as this tells the client * we're finished. */ - SCVAL(req->inbuf,smb_com,SMBwritec); + SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec); if (srv_is_signing_active(req->sconn)) { END_PROFILE(SMBwritebraw); @@ -3955,8 +3972,8 @@ void reply_writebraw(struct smb_request *req) on whether we are using the core+ or lanman1.0 protocol */ if(get_Protocol() <= PROTOCOL_COREPLUS) { - numtowrite = SVAL(smb_buf(req->inbuf),-2); - data = smb_buf(req->inbuf); + numtowrite = SVAL(smb_buf_const(req->inbuf),-2); + data = smb_buf_const(req->inbuf); } else { numtowrite = SVAL(req->vwv+10, 0); data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0); @@ -4001,7 +4018,7 @@ void reply_writebraw(struct smb_request *req) total_written = nwritten; /* Allocate a buffer of 64k + length. */ - buf = TALLOC_ARRAY(NULL, char, 65540); + buf = talloc_array(NULL, char, 65540); if (!buf) { reply_nterror(req, NT_STATUS_NO_MEMORY); error_to_writebrawerr(req); @@ -4474,7 +4491,7 @@ void reply_write_and_X(struct smb_request *req) ssize_t nwritten; unsigned int smb_doff; unsigned int smblen; - char *data; + const char *data; NTSTATUS status; int saved_errno = 0; @@ -5815,7 +5832,7 @@ static void rename_open_files(connection_struct *conn, files_struct *fsp; bool did_rename = False; NTSTATUS status; - uint32_t new_name_hash; + uint32_t new_name_hash = 0; for(fsp = file_find_di_first(conn->sconn, lck->id); fsp; fsp = file_find_di_next(fsp)) { @@ -6405,7 +6422,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, /* Quick check for "." and ".." */ if (ISDOT(dname) || ISDOTDOT(dname)) { - if (attrs & aDIR) { + if (attrs & FILE_ATTRIBUTE_DIRECTORY) { sysdir_entry = True; } else { TALLOC_FREE(talloced); @@ -7971,7 +7988,7 @@ void reply_getattrE(struct smb_request *req) srv_put_dos_date2((char *)req->outbuf, smb_vwv4, convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime)); - if (mode & aDIR) { + if (mode & FILE_ATTRIBUTE_DIRECTORY) { SIVAL(req->outbuf, smb_vwv6, 0); SIVAL(req->outbuf, smb_vwv8, 0); } else { diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index b3dd84264a..26185062a6 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -26,6 +26,7 @@ #include "smb_crypt.h" #include "../lib/util/asn1.h" #include "auth.h" +#include "libsmb/libsmb.h" /****************************************************************************** Server side encryption. @@ -133,7 +134,7 @@ static NTSTATUS get_srv_gss_creds(const char *service, NTSTATUS status = NT_STATUS_OK; gss_OID_desc nt_hostbased_service = - {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")}; + {10, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")}; if (asprintf(&host_princ_s, "%s@%s", service, name) == -1) { return NT_STATUS_NO_MEMORY; @@ -195,7 +196,7 @@ static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) gss_cred_id_t srv_cred; fstring fqdn; - name_to_fqdn(fqdn, global_myname()); + name_to_fqdn(fqdn, lp_netbios_name()); strlower_m(fqdn); status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d3c6c1884f..5aa3ddbdc9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -26,7 +26,6 @@ #include "popt_common.h" #include "smbd/smbd.h" #include "smbd/globals.h" -#include "registry.h" #include "registry/reg_init_full.h" #include "libcli/auth/schannel.h" #include "secrets.h" @@ -52,40 +51,6 @@ extern void start_spoolssd(struct event_context *ev_ctx, extern int dcelogin_atmost_once; #endif /* WITH_DFS */ -static void smbd_set_server_fd(int fd) -{ - struct smbd_server_connection *sconn = smbd_server_conn; - char addr[INET6_ADDRSTRLEN]; - const char *name; - - sconn->sock = fd; - - /* - * Initialize sconn->client_id: If we can't find the client's - * name, default to its address. - */ - - client_addr(fd, sconn->client_id.addr, sizeof(sconn->client_id.addr)); - - name = client_name(sconn->sock); - if (strcmp(name, "UNKNOWN") != 0) { - name = talloc_strdup(sconn, name); - } else { - name = NULL; - } - sconn->client_id.name = - (name != NULL) ? name : sconn->client_id.addr; - - sub_set_socket_ids(sconn->client_id.addr, sconn->client_id.name, - client_socket_addr(sconn->sock, addr, - sizeof(addr))); -} - -struct event_context *smbd_event_context(void) -{ - return server_event_context(); -} - /******************************************************************* What to do when smb.conf is updated. ********************************************************************/ @@ -288,7 +253,7 @@ static void remove_child_pid(pid_t pid, bool unclean_shutdown) if (!cleanup_te) { /* call the cleanup timer, but not too often */ int cleanup_time = lp_parm_int(-1, "smbd", "cleanuptime", 20); - cleanup_te = event_add_timed(smbd_event_context(), NULL, + cleanup_te = event_add_timed(server_event_context(), NULL, timeval_current_ofs(cleanup_time, 0), cleanup_timeout_fn, &cleanup_te); @@ -366,8 +331,8 @@ static void smbd_setup_sig_chld_handler(void) { struct tevent_signal *se; - se = tevent_add_signal(smbd_event_context(), - smbd_event_context(), + se = tevent_add_signal(server_event_context(), + server_event_context(), SIGCHLD, 0, smbd_sig_chld_handler, NULL); @@ -469,7 +434,7 @@ static void smbd_accept_connection(struct tevent_context *ev, s = NULL; status = reinit_after_fork(smbd_messaging_context(), - smbd_event_context(), procid_self(), + server_event_context(), procid_self(), true); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, @@ -582,7 +547,7 @@ static bool smbd_open_one_socket(struct smbd_parent_context *parent, return false; } - s->fde = tevent_add_fd(smbd_event_context(), + s->fde = tevent_add_fd(server_event_context(), s, s->fd, TEVENT_FD_READ, smbd_accept_connection, @@ -632,7 +597,7 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent, { int num_interfaces = iface_count(); int i; - char *ports; + const char *ports; unsigned dns_port = 0; #ifdef HAVE_ATEXIT @@ -763,7 +728,7 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent, return false; } - if (!(event_add_idle(smbd_event_context(), NULL, + if (!(event_add_idle(server_event_context(), NULL, timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0), "parent_housekeeping", smbd_parent_housekeeping, NULL))) { @@ -801,14 +766,14 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent, if (lp_multicast_dns_register() && (dns_port != 0)) { #ifdef WITH_DNSSD_SUPPORT - smbd_setup_mdns_registration(smbd_event_context(), + smbd_setup_mdns_registration(server_event_context(), parent, dns_port); #endif #ifdef WITH_AVAHI_SUPPORT void *avahi_conn; avahi_conn = avahi_start_register( - smbd_event_context(), smbd_event_context(), dns_port); + server_event_context(), server_event_context(), dns_port); if (avahi_conn == NULL) { DEBUG(10, ("avahi_start_register failed\n")); } @@ -827,7 +792,7 @@ static void smbd_parent_loop(struct smbd_parent_context *parent) int ret; TALLOC_CTX *frame = talloc_stackframe(); - ret = tevent_loop_once(smbd_event_context()); + ret = tevent_loop_once(server_event_context()); if (ret != 0) { exit_server_cleanly("tevent_loop_once() error"); } @@ -917,7 +882,7 @@ extern void build_options(bool screen); load_case_tables(); /* Initialize the event context, it will panic on error */ - smbd_event_context(); + server_event_context(); smbd_init_globals(); @@ -1063,7 +1028,7 @@ extern void build_options(bool screen); * Reloading of the printers will not work here as we don't have a * server info and rpc services set up. It will be called later. */ - if (!reload_services(smbd_messaging_context(), -1, False)) { + if (!reload_services(NULL, -1, False)) { exit(1); } @@ -1124,7 +1089,7 @@ extern void build_options(bool screen); pidfile_create("smbd"); status = reinit_after_fork(smbd_messaging_context(), - smbd_event_context(), + server_event_context(), procid_self(), false); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); @@ -1134,7 +1099,7 @@ extern void build_options(bool screen); smbd_server_conn->msg_ctx = smbd_messaging_context(); smbd_setup_sig_term_handler(); - smbd_setup_sig_hup_handler(smbd_event_context(), + smbd_setup_sig_hup_handler(server_event_context(), smbd_server_conn->msg_ctx); /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ @@ -1148,7 +1113,7 @@ extern void build_options(bool screen); /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ - if(!initialize_password_db(False, smbd_event_context())) + if(!initialize_password_db(False, server_event_context())) exit(1); if (!secrets_init()) { @@ -1178,15 +1143,15 @@ extern void build_options(bool screen); if (!locking_init()) exit(1); - if (!messaging_tdb_parent_init(smbd_event_context())) { + if (!messaging_tdb_parent_init(server_event_context())) { exit(1); } - if (!notify_internal_parent_init(smbd_event_context())) { + if (!notify_internal_parent_init(server_event_context())) { exit(1); } - if (!serverid_parent_init(smbd_event_context())) { + if (!serverid_parent_init(server_event_context())) { exit(1); } @@ -1232,13 +1197,13 @@ extern void build_options(bool screen); rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM, "rpc_server", "epmapper", "none"); - if (StrCaseCmp(rpcsrv_type, "daemon") == 0) { - start_epmd(smbd_event_context(), + if (strcasecmp_m(rpcsrv_type, "daemon") == 0) { + start_epmd(server_event_context(), smbd_server_conn->msg_ctx); } } - if (!dcesrv_ep_setup(smbd_event_context(), smbd_server_conn->msg_ctx)) { + if (!dcesrv_ep_setup(server_event_context(), smbd_server_conn->msg_ctx)) { exit(1); } @@ -1253,7 +1218,7 @@ extern void build_options(bool screen); if (is_daemon && !interactive && lp_parm_bool(-1, "smbd", "backgroundqueue", true)) { - start_background_queue(smbd_event_context(), + start_background_queue(server_event_context(), smbd_messaging_context()); } @@ -1265,8 +1230,8 @@ extern void build_options(bool screen); rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM, "rpc_server", "spoolss", "embedded"); - if (StrCaseCmp(rpcsrv_type, "daemon") == 0) { - start_spoolssd(smbd_event_context(), + if (strcasecmp_m(rpcsrv_type, "daemon") == 0) { + start_spoolssd(server_event_context(), smbd_messaging_context()); } } @@ -1296,7 +1261,7 @@ extern void build_options(bool screen); return(0); } - parent = talloc_zero(smbd_event_context(), struct smbd_parent_context); + parent = talloc_zero(server_event_context(), struct smbd_parent_context); if (!parent) { exit_server("talloc(struct smbd_parent_context) failed"); } diff --git a/source3/smbd/server_exit.c b/source3/smbd/server_exit.c index 554affc984..c7a318d891 100644 --- a/source3/smbd/server_exit.c +++ b/source3/smbd/server_exit.c @@ -25,7 +25,7 @@ #include "includes.h" #include "smbd/smbd.h" #include "smbd/globals.h" - +#include "ntdomain.h" #include "../librpc/gen_ndr/srv_dfs.h" #include "../librpc/gen_ndr/srv_dssetup.h" #include "../librpc/gen_ndr/srv_echo.h" diff --git a/source3/smbd/server_reload.c b/source3/smbd/server_reload.c index 82b0cb03e9..fef66dac6a 100644 --- a/source3/smbd/server_reload.c +++ b/source3/smbd/server_reload.c @@ -113,7 +113,11 @@ bool reload_services(struct messaging_context *msg_ctx, int smb_sock, if (test && !lp_file_list_changed()) return(True); - lp_killunused(conn_snum_used); + if (msg_ctx) { + lp_killunused(msg_ctx_to_sconn(msg_ctx), conn_snum_used); + } else { + lp_killunused(NULL, NULL); + } ret = lp_load(get_dyn_CONFIGFILE(), False, False, True, True); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index b29713d21d..0857645d1c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -19,6 +19,7 @@ #include "includes.h" #include "system/filesys.h" +#include "../lib/tsocket/tsocket.h" #include "smbd/smbd.h" #include "smbd/globals.h" #include "../librpc/gen_ndr/netlogon.h" @@ -221,232 +222,6 @@ bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir) return(True); } -static int load_registry_service(const char *servicename) -{ - if (!lp_registry_shares()) { - return -1; - } - - if ((servicename == NULL) || (*servicename == '\0')) { - return -1; - } - - if (strequal(servicename, GLOBAL_NAME)) { - return -2; - } - - if (!process_registry_service(servicename)) { - return -1; - } - - return lp_servicenumber(servicename); -} - -void load_registry_shares(void) -{ - DEBUG(8, ("load_registry_shares()\n")); - if (!lp_registry_shares()) { - return; - } - - process_registry_shares(); - - return; -} - -/**************************************************************************** - Add a home service. Returns the new service number or -1 if fail. -****************************************************************************/ - -int add_home_service(const char *service, const char *username, const char *homedir) -{ - int iHomeService; - - if (!service || !homedir || homedir[0] == '\0') - return -1; - - if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) { - if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) { - return -1; - } - } - - /* - * If this is a winbindd provided username, remove - * the domain component before adding the service. - * Log a warning if the "path=" parameter does not - * include any macros. - */ - - { - const char *p = strchr(service,*lp_winbind_separator()); - - /* We only want the 'user' part of the string */ - if (p) { - service = p + 1; - } - } - - if (!lp_add_home(service, iHomeService, username, homedir)) { - return -1; - } - - return lp_servicenumber(service); - -} - -/** - * Find a service entry. - * - * @param service is modified (to canonical form??) - **/ - -int find_service(TALLOC_CTX *ctx, const char *service_in, char **p_service_out) -{ - int iService; - - if (!service_in) { - return -1; - } - - /* First make a copy. */ - *p_service_out = talloc_strdup(ctx, service_in); - if (!*p_service_out) { - return -1; - } - - all_string_sub(*p_service_out,"\\","/",0); - - iService = lp_servicenumber(*p_service_out); - - /* now handle the special case of a home directory */ - if (iService < 0) { - char *phome_dir = get_user_home_dir(ctx, *p_service_out); - - if(!phome_dir) { - /* - * Try mapping the servicename, it may - * be a Windows to unix mapped user name. - */ - if(map_username(ctx, *p_service_out, p_service_out)) { - if (*p_service_out == NULL) { - /* Out of memory. */ - return -1; - } - phome_dir = get_user_home_dir( - ctx, *p_service_out); - } - } - - DEBUG(3,("checking for home directory %s gave %s\n",*p_service_out, - phome_dir?phome_dir:"(NULL)")); - - iService = add_home_service(*p_service_out,*p_service_out /* 'username' */, phome_dir); - } - - /* If we still don't have a service, attempt to add it as a printer. */ - if (iService < 0) { - int iPrinterService; - - if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) { - iPrinterService = load_registry_service(PRINTERS_NAME); - } - if (iPrinterService >= 0) { - DEBUG(3,("checking whether %s is a valid printer name...\n", - *p_service_out)); - if (pcap_printername_ok(*p_service_out)) { - DEBUG(3,("%s is a valid printer name\n", - *p_service_out)); - DEBUG(3,("adding %s as a printer service\n", - *p_service_out)); - lp_add_printer(*p_service_out, iPrinterService); - iService = lp_servicenumber(*p_service_out); - if (iService < 0) { - DEBUG(0,("failed to add %s as a printer service!\n", - *p_service_out)); - } - } else { - DEBUG(3,("%s is not a valid printer name\n", - *p_service_out)); - } - } - } - - /* Check for default vfs service? Unsure whether to implement this */ - if (iService < 0) { - } - - if (iService < 0) { - iService = load_registry_service(*p_service_out); - } - - /* Is it a usershare service ? */ - if (iService < 0 && *lp_usershare_path()) { - /* Ensure the name is canonicalized. */ - strlower_m(*p_service_out); - iService = load_usershare_service(*p_service_out); - } - - /* just possibly it's a default service? */ - if (iService < 0) { - char *pdefservice = lp_defaultservice(); - if (pdefservice && - *pdefservice && - !strequal(pdefservice, *p_service_out) - && !strstr_m(*p_service_out,"..")) { - /* - * We need to do a local copy here as lp_defaultservice() - * returns one of the rotating lp_string buffers that - * could get overwritten by the recursive find_service() call - * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>. - */ - char *defservice = talloc_strdup(ctx, pdefservice); - - if (!defservice) { - goto fail; - } - - /* Disallow anything except explicit share names. */ - if (strequal(defservice,HOMES_NAME) || - strequal(defservice, PRINTERS_NAME) || - strequal(defservice, "IPC$")) { - TALLOC_FREE(defservice); - goto fail; - } - - iService = find_service(ctx, defservice, p_service_out); - if (!*p_service_out) { - TALLOC_FREE(defservice); - iService = -1; - goto fail; - } - if (iService >= 0) { - all_string_sub(*p_service_out, "_","/",0); - iService = lp_add_service(*p_service_out, iService); - } - TALLOC_FREE(defservice); - } - } - - if (iService >= 0) { - if (!VALID_SNUM(iService)) { - DEBUG(0,("Invalid snum %d for %s\n",iService, - *p_service_out)); - iService = -1; - } - } - - fail: - - if (iService < 0) { - DEBUG(3,("find_service() failed to find service %s\n", - *p_service_out)); - } - - return (iService); -} - - /**************************************************************************** do some basic sainity checks on the share. This function modifies dev, ecode. @@ -930,7 +705,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, conn->notify_ctx = notify_init(conn, sconn_server_id(sconn), sconn->msg_ctx, - smbd_event_context(), + server_event_context(), conn); } diff --git a/source3/smbd/session.c b/source3/smbd/session.c index f3a678b205..48afb5389f 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -231,7 +231,7 @@ static int gather_sessioninfo(const char *key, struct sessionid *session, { struct session_list *sesslist = (struct session_list *)private_data; - sesslist->sessions = TALLOC_REALLOC_ARRAY( + sesslist->sessions = talloc_realloc( sesslist->mem_ctx, sesslist->sessions, struct sessionid, sesslist->count+1); @@ -264,7 +264,7 @@ int list_sessions(TALLOC_CTX *mem_ctx, struct sessionid **session_list) sesslist.sessions = NULL; ret = sessionid_traverse_read(gather_sessioninfo, (void *) &sesslist); - if (ret == -1) { + if (ret < 0) { DEBUG(3, ("Session traverse failed\n")); SAFE_FREE(sesslist.sessions); *session_list = NULL; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 3cf6758e29..dda4ef296e 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -23,6 +23,7 @@ */ #include "includes.h" +#include "../lib/tsocket/tsocket.h" #include "smbd/smbd.h" #include "smbd/globals.h" #include "../libcli/auth/spnego.h" @@ -193,7 +194,7 @@ static bool make_krb5_skew_error(DATA_BLOB *pblob_out) return False; } /* Create server principal. */ - asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm()); + asprintf(&host_princ_s, "%s$@%s", lp_netbios_name(), lp_realm()); if (!host_princ_s) { goto out; } @@ -929,13 +930,28 @@ static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn, } asn1_load(data, *pblob); - asn1_start_tag(data, pblob->data[0]); - if (data->has_error || data->nesting == NULL) { + if (asn1_start_tag(data, pblob->data[0])) { + /* asn1_start_tag checks if the given + length of the blob is enough to complete + the tag. If it returns true we know + there is nothing to do - the blob is + complete. */ asn1_free(data); - /* Let caller catch. */ return NT_STATUS_OK; } + if (data->nesting == NULL) { + /* Incorrect tag, allocation failed, + or reading the tag length failed. + Let the caller catch. */ + asn1_free(data); + return NT_STATUS_OK; + } + + /* Here we know asn1_start_tag() has set data->has_error to true. + asn1_tag_remaining() will have failed due to the given blob + being too short. We need to work out how short. */ + /* Integer wrap paranoia.... */ if (data->nesting->taglen + data->nesting->start < data->nesting->taglen || @@ -964,6 +980,13 @@ static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn, if (needed_len <= pblob->length) { /* Nothing to do - blob is complete. */ + /* THIS SHOULD NOT HAPPEN - asn1_start_tag() + above should have caught this !!! */ + DEBUG(0,("check_spnego_blob_complete: logic " + "error (needed_len = %u, " + "pblob->length = %u).\n", + (unsigned int)needed_len, + (unsigned int)pblob->length )); return NT_STATUS_OK; } @@ -1042,7 +1065,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) file_save("negotiate.dat", blob1.data, blob1.length); #endif - p2 = (char *)req->buf + blob1.length; + p2 = (const char *)req->buf + blob1.length; p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2, STR_TERMINATE); @@ -1200,7 +1223,7 @@ static int shutdown_other_smbds(const struct connections_key *key, struct shutdown_state *state = (struct shutdown_state *)private_data; DEBUG(10, ("shutdown_other_smbds: %s, %s\n", - procid_str(talloc_tos(), &crec->pid), crec->addr)); + server_id_str(talloc_tos(), &crec->pid), crec->addr)); if (!process_exists(crec->pid)) { DEBUG(10, ("process does not exist\n")); @@ -1684,7 +1707,7 @@ void reply_sesssetup_and_X(struct smb_request *req) data_blob_free(&lm_resp); SSVAL(req->outbuf,smb_uid,sess_vuid); - SSVAL(req->inbuf,smb_uid,sess_vuid); + SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid); req->vuid = sess_vuid; if (!sconn->smb1.sessions.done_sesssetup) { diff --git a/source3/smbd/signing.c b/source3/smbd/signing.c index bea2409883..25b3c40d7d 100644 --- a/source3/smbd/signing.c +++ b/source3/smbd/signing.c @@ -176,7 +176,7 @@ bool srv_init_signing(struct smbd_server_connection *conn) struct smbd_shm_signing *s; /* setup the signing state in shared memory */ - s = talloc_zero(smbd_event_context(), struct smbd_shm_signing); + s = talloc_zero(server_event_context(), struct smbd_shm_signing); if (s == NULL) { return false; } @@ -198,7 +198,7 @@ bool srv_init_signing(struct smbd_server_connection *conn) return true; } - conn->smb1.signing_state = smb_signing_init(smbd_event_context(), + conn->smb1.signing_state = smb_signing_init(server_event_context(), allowed, mandatory); if (!conn->smb1.signing_state) { return false; diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c index 925384c3bf..5d5ab4139d 100644 --- a/source3/smbd/smb2_break.c +++ b/source3/smbd/smb2_break.c @@ -23,6 +23,7 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" +#include "../lib/util/tevent_ntstatus.h" static struct tevent_req *smbd_smb2_oplock_break_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index 6e292468f9..73b8ade5bd 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -25,6 +25,7 @@ #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" #include "../librpc/gen_ndr/ndr_security.h" +#include "../lib/util/tevent_ntstatus.h" int map_smb2_oplock_levels_to_samba(uint8_t in_oplock_level) { diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c index 3ac573c213..9fc8f1fef2 100644 --- a/source3/smbd/smb2_find.c +++ b/source3/smbd/smb2_find.c @@ -23,6 +23,7 @@ #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" #include "trans2.h" +#include "../lib/util/tevent_ntstatus.h" static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -228,7 +229,7 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx, int last_entry_off = 0; int off = 0; uint32_t num = 0; - uint32_t dirtype = aHIDDEN | aSYSTEM | aDIR; + uint32_t dirtype = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY; bool dont_descend = false; bool ask_sharemode = true; diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c index 9395592907..c3f5a30129 100644 --- a/source3/smbd/smb2_flush.c +++ b/source3/smbd/smb2_flush.c @@ -22,6 +22,7 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" +#include "../lib/util/tevent_ntstatus.h" static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index 1d6b862d6a..3c8c690342 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -24,6 +24,7 @@ #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" #include "trans2.h" +#include "../lib/util/tevent_ntstatus.h" static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, diff --git a/source3/smbd/smb2_ioctl.c b/source3/smbd/smb2_ioctl.c index 6ee9318212..bce02b0a3a 100644 --- a/source3/smbd/smb2_ioctl.c +++ b/source3/smbd/smb2_ioctl.c @@ -22,6 +22,9 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" +#include "../lib/util/tevent_ntstatus.h" +#include "rpc_server/srv_pipe_hnd.h" +#include "include/ntioctl.h" static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -242,8 +245,9 @@ static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx, state->in_max_output = in_max_output; state->out_output = data_blob_null; - DEBUG(10,("smbd_smb2_ioctl: file_id[0x%016llX]\n", - (unsigned long long)in_file_id_volatile)); + DEBUG(10, ("smbd_smb2_ioctl: ctl_code[0x%08x] file_id[0x%016llX]\n", + (unsigned)in_ctl_code, + (unsigned long long)in_file_id_volatile)); smbreq = smbd_smb2_fake_smb_request(smb2req); if (tevent_req_nomem(smbreq, req)) { @@ -375,6 +379,131 @@ static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx, req); return req; + case 0x00144064: /* FSCTL_SRV_ENUMERATE_SNAPSHOTS */ + { + /* + * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots) + * and return their volume names. If max_data_count is 16, then it is just + * asking for the number of volumes and length of the combined names. + * + * pdata is the data allocated by our caller, but that uses + * total_data_count (which is 0 in our case) rather than max_data_count. + * Allocate the correct amount and return the pointer to let + * it be deallocated when we return. + */ + struct shadow_copy_data *shadow_data = NULL; + bool labels = False; + uint32_t labels_data_count = 0; + uint32_t data_count; + uint32_t i; + char *pdata; + NTSTATUS status; + + if (fsp == NULL) { + tevent_req_nterror(req, NT_STATUS_FILE_CLOSED); + return tevent_req_post(req, ev); + } + + if (in_max_output < 16) { + DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: " + "in_max_output(%u) < 16 is invalid!\n", + in_max_output)); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + + if (in_max_output > 16) { + labels = True; + } + + shadow_data = talloc_zero(talloc_tos(), + struct shadow_copy_data); + if (tevent_req_nomem(shadow_data, req)) { + DEBUG(0,("TALLOC_ZERO() failed!\n")); + return tevent_req_post(req, ev); + } + + /* + * Call the VFS routine to actually do the work. + */ + if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels) + != 0) { + if (errno == ENOSYS) { + DEBUG(5, ("FSCTL_GET_SHADOW_COPY_DATA: " + "connectpath %s, not supported.\n", + smbreq->conn->connectpath)); + status = NT_STATUS_NOT_SUPPORTED; + } else { + DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: " + "connectpath %s, failed.\n", + smbreq->conn->connectpath)); + status = map_nt_error_from_unix(errno); + } + TALLOC_FREE(shadow_data); + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + + labels_data_count = + (shadow_data->num_volumes*2*sizeof(SHADOW_COPY_LABEL)) + + 2; + + if (labels) { + data_count = 12+labels_data_count+4; + } else { + data_count = 16; + } + + if (labels && (in_max_output < data_count)) { + DEBUG(0, ("FSCTL_GET_SHADOW_COPY_DATA: " + "in_max_output(%u) too small (%u) bytes " + "needed!\n", in_max_output, data_count)); + TALLOC_FREE(shadow_data); + tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); + return tevent_req_post(req, ev); + } + + state->out_output = data_blob_talloc(state, NULL, data_count); + if (tevent_req_nomem(state->out_output.data, req)) { + return tevent_req_post(req, ev); + } + + pdata = (char *)state->out_output.data; + + /* num_volumes 4 bytes */ + SIVAL(pdata, 0, shadow_data->num_volumes); + + if (labels) { + /* num_labels 4 bytes */ + SIVAL(pdata, 4, shadow_data->num_volumes); + } + + /* needed_data_count 4 bytes */ + SIVAL(pdata, 8, labels_data_count+4); + + pdata += 12; + + DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for " + "path[%s].\n", + shadow_data->num_volumes, fsp_str_dbg(fsp))); + if (labels && shadow_data->labels) { + for (i=0; i<shadow_data->num_volumes; i++) { + srvstr_push(pdata, smbreq->flags2, + pdata, shadow_data->labels[i], + 2*sizeof(SHADOW_COPY_LABEL), + STR_UNICODE|STR_TERMINATE); + pdata += 2*sizeof(SHADOW_COPY_LABEL); + DEBUGADD(10, ("Label[%u]: '%s'\n", i, + shadow_data->labels[i])); + } + } + + TALLOC_FREE(shadow_data); + + tevent_req_done(req); + return tevent_req_post(req, ev); + } + default: if (IS_IPC(smbreq->conn)) { tevent_req_nterror(req, NT_STATUS_FS_DRIVER_REQUIRED); diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index dcf1e0c6a5..5d615e1bed 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -23,6 +23,7 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" +#include "../lib/util/tevent_ntstatus.h" #include "messages.h" struct smbd_smb2_lock_element { @@ -567,7 +568,7 @@ static bool recalc_smb2_brl_timeout(struct smbd_server_connection *sconn) } sconn->smb2.locks.brl_timeout = event_add_timed( - smbd_event_context(), + server_event_context(), NULL, next_timeout, brl_timeout_fn, @@ -627,9 +628,7 @@ bool push_blocking_lock_request_smb2( struct byte_range_lock *br_lck, blr->expire_time.tv_sec = 0; blr->expire_time.tv_usec = 0; /* Never expire. */ } else { - blr->expire_time = timeval_current_ofs( - lock_timeout/1000, - (lock_timeout % 1000) * 1000); + blr->expire_time = timeval_current_ofs_msec(lock_timeout); } blr->lock_num = lock_num; diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index 1e02c88d3d..f639503ad4 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -78,7 +78,7 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) uint16_t dialect = 0; uint32_t capabilities; -/* TODO: drop the connection with INVALI_PARAMETER */ +/* TODO: drop the connection with INVALID_PARAMETER */ if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) { return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); @@ -177,5 +177,7 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) outdyn = security_buffer; + req->sconn->using_smb2 = true; + return smbd_smb2_request_done(req, outbody, &outdyn); } diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c index d52b2878ec..9e377ceda4 100644 --- a/source3/smbd/smb2_notify.c +++ b/source3/smbd/smb2_notify.c @@ -23,6 +23,7 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" +#include "../lib/util/tevent_ntstatus.h" struct smbd_smb2_notify_state { struct smbd_smb2_request *smb2req; diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c index bffda89010..6e686ef273 100644 --- a/source3/smbd/smb2_read.c +++ b/source3/smbd/smb2_read.c @@ -24,6 +24,8 @@ #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" #include "libcli/security/security.h" +#include "../lib/util/tevent_ntstatus.h" +#include "rpc_server/srv_pipe_hnd.h" static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -306,7 +308,7 @@ static NTSTATUS schedule_smb2_sendfile_read(struct smbd_smb2_request *smb2req, /* Make a copy of state attached to the smb2req. Attach the destructor here as this will trigger the sendfile call when the request is destroyed. */ - state_copy = TALLOC_P(smb2req, struct smbd_smb2_read_state); + state_copy = talloc(smb2req, struct smbd_smb2_read_state); if (!state_copy) { return NT_STATUS_NO_MEMORY; } @@ -442,7 +444,7 @@ static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - subreq = np_read_send(state, smbd_event_context(), + subreq = np_read_send(state, server_event_context(), fsp->fake_file_handle, state->out_data.data, state->out_data.length); diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 0004e7ca8c..65bb5b9eb0 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -24,6 +24,7 @@ #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" #include "../lib/tsocket/tsocket.h" +#include "../lib/util/tevent_ntstatus.h" #include "smbprofile.h" #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9) @@ -94,7 +95,7 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn) TALLOC_FREE(sconn->smb1.fde); - sconn->smb2.event_ctx = smbd_event_context(); + sconn->smb2.event_ctx = server_event_context(); sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue"); if (sconn->smb2.recv_queue == NULL) { @@ -268,15 +269,15 @@ static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn, memcpy(req->in.nbt_hdr, inbuf, 4); ofs = 0; - req->in.vector[0].iov_base = (void *)req->in.nbt_hdr; + req->in.vector[0].iov_base = discard_const_p(void, req->in.nbt_hdr); req->in.vector[0].iov_len = 4; ofs += req->in.vector[0].iov_len; - req->in.vector[1].iov_base = (void *)(inbuf + ofs); + req->in.vector[1].iov_base = discard_const_p(void, (inbuf + ofs)); req->in.vector[1].iov_len = SMB2_HDR_BODY; ofs += req->in.vector[1].iov_len; - req->in.vector[2].iov_base = (void *)(inbuf + ofs); + req->in.vector[2].iov_base = discard_const_p(void, (inbuf + ofs)); req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE; ofs += req->in.vector[2].iov_len; @@ -284,7 +285,7 @@ static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn, return NT_STATUS_INVALID_PARAMETER; } - req->in.vector[3].iov_base = (void *)(inbuf + ofs); + req->in.vector[3].iov_base = discard_const_p(void, (inbuf + ofs)); req->in.vector[3].iov_len = size - ofs; ofs += req->in.vector[3].iov_len; @@ -607,7 +608,7 @@ static bool dup_smb2_vec3(TALLOC_CTX *ctx, srcvec[1].iov_base == ((uint8_t *)srcvec[0].iov_base) + SMB2_HDR_BODY) { - outvec[1].iov_base = ((uint8_t *)outvec[1].iov_base) + + outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) + SMB2_HDR_BODY; outvec[1].iov_len = 8; } else { @@ -2017,9 +2018,11 @@ static int smbd_smb2_request_next_vector(struct tstream_context *stream, invalid = true; } - if ((body_size % 2) != 0) { - body_size -= 1; - } + /* + * Mask out the lowest bit, the "dynamic" part + * of body_size. + */ + body_size &= ~1; if (body_size > (full_size - SMB2_HDR_BODY)) { /* diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index d727ee98b0..c33d1c61be 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -844,7 +844,7 @@ NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req) if (chained_fixup) { /* Fix up our own outhdr. */ outhdr = (const uint8_t *)req->out.vector[i].iov_base; - SBVAL(outhdr, SMB2_HDR_SESSION_ID, in_session_id); + SBVAL(discard_const_p(uint8_t, outhdr), SMB2_HDR_SESSION_ID, in_session_id); } return NT_STATUS_OK; } diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c index 39b7aee76b..e1149408d1 100644 --- a/source3/smbd/smb2_setinfo.c +++ b/source3/smbd/smb2_setinfo.c @@ -24,6 +24,7 @@ #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" #include "trans2.h" +#include "../lib/util/tevent_ntstatus.h" static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c index bdd18d5d07..1b4aa79070 100644 --- a/source3/smbd/smb2_tcon.c +++ b/source3/smbd/smb2_tcon.c @@ -331,7 +331,7 @@ NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req) if (chained_fixup) { /* Fix up our own outhdr. */ outhdr = (const uint8_t *)req->out.vector[i].iov_base; - SIVAL(outhdr, SMB2_HDR_TID, in_tid); + SIVAL(discard_const_p(uint8_t, outhdr), SMB2_HDR_TID, in_tid); } return NT_STATUS_OK; diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c index 413fe0c7d1..057abcc8f7 100644 --- a/source3/smbd/smb2_write.c +++ b/source3/smbd/smb2_write.c @@ -22,6 +22,8 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" +#include "../lib/util/tevent_ntstatus.h" +#include "rpc_server/srv_pipe_hnd.h" static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -281,7 +283,7 @@ static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - subreq = np_write_send(state, smbd_event_context(), + subreq = np_write_send(state, server_event_context(), fsp->fake_file_handle, in_data.data, in_data.length); diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index 050de599a5..c069dd4a5e 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -56,7 +56,7 @@ ssize_t message_push_string(uint8 **outbuf, const char *str, int flags) */ grow_size = (strlen(str) + 2) * 4; - if (!(tmp = TALLOC_REALLOC_ARRAY(NULL, *outbuf, uint8, + if (!(tmp = talloc_realloc(NULL, *outbuf, uint8, buf_size + grow_size))) { DEBUG(0, ("talloc failed\n")); return -1; diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 5c74b92855..963b7c4bc1 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -25,6 +25,7 @@ #include "smbd/smbd.h" #include "messages.h" #include "smbprofile.h" +#include "tdb_compat.h" /**************************************************************************** Stat cache code used in unix_convert. @@ -339,8 +340,8 @@ bool stat_cache_lookup(connection_struct *conn, Tell all smbd's to delete an entry. **************************************************************************/ -void send_stat_cache_delete_message(struct messaging_context *msg_ctx, - const char *name) +void smbd_send_stat_cache_delete_message(struct messaging_context *msg_ctx, + const char *name) { #ifdef DEVELOPER message_send_all(msg_ctx, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 507ae9ba93..b853722eae 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -35,6 +35,7 @@ #include "trans2.h" #include "auth.h" #include "smbprofile.h" +#include "rpc_server/srv_pipe_hnd.h" #define DIR_ENTRY_SAFETY_MARGIN 4096 @@ -106,7 +107,7 @@ static bool samba_private_attr_name(const char *unix_ea_name) if (strequal( prohibited_ea_names[i], unix_ea_name)) return true; } - if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX, + if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX, strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) { return true; } @@ -128,7 +129,7 @@ NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, again: - val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size); + val = talloc_realloc(mem_ctx, val, char, attr_size); if (!val) { return NT_STATUS_NO_MEMORY; } @@ -191,7 +192,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, * TALLOC the result early to get the talloc hierarchy right. */ - names = TALLOC_ARRAY(mem_ctx, char *, 1); + names = talloc_array(mem_ctx, char *, 1); if (names == NULL) { DEBUG(0, ("talloc failed\n")); return NT_STATUS_NO_MEMORY; @@ -199,7 +200,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, while (ea_namelist_size <= 65536) { - ea_namelist = TALLOC_REALLOC_ARRAY( + ea_namelist = talloc_realloc( names, ea_namelist, char, ea_namelist_size); if (ea_namelist == NULL) { DEBUG(0, ("talloc failed\n")); @@ -258,7 +259,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, num_names += 1; } - tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names); + tmp = talloc_realloc(mem_ctx, names, char *, num_names); if (tmp == NULL) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(names); @@ -315,7 +316,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str || samba_private_attr_name(names[i])) continue; - listp = TALLOC_P(mem_ctx, struct ea_list); + listp = talloc(mem_ctx, struct ea_list); if (listp == NULL) { return NULL; } @@ -387,7 +388,7 @@ static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned in SCVAL(p,0,ea_list->ea.flags); SCVAL(p,1,dos_namelen); SSVAL(p,2,ea_list->ea.value.length); - fstrcpy(p+4, dos_ea_name); + strlcpy(p+4, dos_ea_name, dos_namelen+1); memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length); total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length; @@ -451,7 +452,7 @@ static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx, SCVAL(p, 0x04, ea_list->ea.flags); SCVAL(p, 0x05, dos_namelen); SSVAL(p, 0x06, ea_list->ea.value.length); - fstrcpy((char *)(p+0x08), dos_ea_name); + strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1); memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length); total_data_size -= this_size; @@ -490,7 +491,7 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con if (strequal(&unix_ea_name[5], ea_list->ea.name)) { DEBUG(10,("canonicalize_ea_name: %s -> %s\n", &unix_ea_name[5], ea_list->ea.name)); - safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6); + strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5); break; } } @@ -589,7 +590,7 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz size_t converted_size, offset = 0; while (offset + 2 < data_size) { - struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); + struct ea_list *eal = talloc_zero(ctx, struct ea_list); unsigned int namelen = CVAL(pdata,offset); offset++; /* Go past the namelen byte. */ @@ -627,7 +628,7 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used) { - struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); + struct ea_list *eal = talloc_zero(ctx, struct ea_list); uint16 val_len; unsigned int namelen; size_t converted_size; @@ -1148,7 +1149,7 @@ static void call_trans2open(connection_struct *conn, fattr = dos_mode(conn, smb_fname); mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime); inode = smb_fname->st.st_ex_ino; - if (fattr & aDIR) { + if (fattr & FILE_ATTRIBUTE_DIRECTORY) { close_file(req, fsp, ERROR_CLOSE); reply_nterror(req, NT_STATUS_ACCESS_DENIED); goto out; @@ -1218,7 +1219,7 @@ static bool exact_match(bool has_wild, if (case_sensitive) { return strcmp(str,mask)==0; } else { - return StrCaseCmp(str,mask) == 0; + return strcasecmp_m(str,mask) == 0; } } @@ -1524,7 +1525,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, ZERO_STRUCT(create_date_ts); ZERO_STRUCT(cdate_ts); - if (!(mode & aDIR)) { + if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) { file_size = get_file_size_stat(&smb_fname->st); } allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st); @@ -3733,36 +3734,10 @@ cap_low = 0x%x, cap_high = 0x%x\n", /* unknown_1 24 NULL bytes in pdata*/ /* the soft quotas 8 bytes (uint64_t)*/ - quotas.softlim = (uint64_t)IVAL(pdata,24); -#ifdef LARGE_SMB_OFF_T - quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32); -#else /* LARGE_SMB_OFF_T */ - if ((IVAL(pdata,28) != 0)&& - ((quotas.softlim != 0xFFFFFFFF)|| - (IVAL(pdata,28)!=0xFFFFFFFF))) { - /* more than 32 bits? */ - reply_nterror( - req, - NT_STATUS_INVALID_PARAMETER); - return; - } -#endif /* LARGE_SMB_OFF_T */ + quotas.softlim = BVAL(pdata,24); /* the hard quotas 8 bytes (uint64_t)*/ - quotas.hardlim = (uint64_t)IVAL(pdata,32); -#ifdef LARGE_SMB_OFF_T - quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32); -#else /* LARGE_SMB_OFF_T */ - if ((IVAL(pdata,36) != 0)&& - ((quotas.hardlim != 0xFFFFFFFF)|| - (IVAL(pdata,36)!=0xFFFFFFFF))) { - /* more than 32 bits? */ - reply_nterror( - req, - NT_STATUS_INVALID_PARAMETER); - return; - } -#endif /* LARGE_SMB_OFF_T */ + quotas.hardlim = BVAL(pdata,32); /* quota_flags 2 bytes **/ quotas.qflags = SVAL(pdata,40); @@ -4253,7 +4228,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, mode = dos_mode(conn, smb_fname); nlink = psbuf->st_ex_nlink; - if (nlink && (mode&aDIR)) { + if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) { nlink = 1; } @@ -4334,7 +4309,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, } } - if (!(mode & aDIR)) { + if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) { file_size = get_file_size_stat(psbuf); } @@ -4504,7 +4479,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, SOFF_T(pdata,8,file_size); SIVAL(pdata,16,nlink); SCVAL(pdata,20,delete_pending?1:0); - SCVAL(pdata,21,(mode&aDIR)?1:0); + SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0); SSVAL(pdata,22,0); /* Padding. */ break; @@ -4587,7 +4562,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, SOFF_T(pdata,8,file_size); SIVAL(pdata,16,nlink); SCVAL(pdata,20,delete_pending); - SCVAL(pdata,21,(mode&aDIR)?1:0); + SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0); SSVAL(pdata,22,0); pdata += 24; SIVAL(pdata,0,ea_size); @@ -4618,7 +4593,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, SBVAL(pdata, 0x30, file_size); SIVAL(pdata, 0x38, nlink); SCVAL(pdata, 0x3C, delete_pending); - SCVAL(pdata, 0x3D, (mode&aDIR)?1:0); + SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0); SSVAL(pdata, 0x3E, 0); /* padding */ SBVAL(pdata, 0x40, file_index); SIVAL(pdata, 0x48, ea_size); @@ -4793,7 +4768,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_UNIX_LINK: { int len; - char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1); + char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1); if (!buffer) { return NT_STATUS_NO_MEMORY; @@ -5326,7 +5301,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } /* Copy the lock range data. */ - lock_data = (char *)TALLOC_MEMDUP( + lock_data = (char *)talloc_memdup( req, pdata, total_data); if (!lock_data) { reply_nterror(req, NT_STATUS_NO_MEMORY); @@ -5580,9 +5555,9 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn, if (dosmode) { if (S_ISDIR(smb_fname_base->st.st_ex_mode)) { - dosmode |= aDIR; + dosmode |= FILE_ATTRIBUTE_DIRECTORY; } else { - dosmode &= ~aDIR; + dosmode &= ~FILE_ATTRIBUTE_DIRECTORY; } } @@ -6075,8 +6050,9 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn, "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n", fsp->fnum, fsp_str_dbg(fsp), smb_fname_str_dbg(smb_fname_dst))); - status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0, - overwrite); + status = rename_internals_fsp(conn, fsp, smb_fname_dst, + (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM), + overwrite); out: TALLOC_FREE(smb_fname_dst); @@ -7251,6 +7227,9 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, Open/Create a file with POSIX semantics. ****************************************************************************/ +#define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA) +#define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA) + static NTSTATUS smb_posix_open(connection_struct *conn, struct smb_request *req, char **ppdata, @@ -7266,7 +7245,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn, uint32 mod_unixmode = 0; uint32 create_disp = 0; uint32 access_mask = 0; - uint32 create_options = 0; + uint32 create_options = FILE_NON_DIRECTORY_FILE; NTSTATUS status = NT_STATUS_OK; mode_t unixmode = (mode_t)0; files_struct *fsp = NULL; @@ -7296,13 +7275,14 @@ static NTSTATUS smb_posix_open(connection_struct *conn, switch (wire_open_mode & SMB_ACCMODE) { case SMB_O_RDONLY: - access_mask = FILE_READ_DATA; + access_mask = SMB_O_RDONLY_MAPPING; break; case SMB_O_WRONLY: - access_mask = FILE_WRITE_DATA; + access_mask = SMB_O_WRONLY_MAPPING; break; case SMB_O_RDWR: - access_mask = FILE_READ_DATA|FILE_WRITE_DATA; + access_mask = (SMB_O_RDONLY_MAPPING| + SMB_O_WRONLY_MAPPING); break; default: DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n", @@ -7312,18 +7292,55 @@ static NTSTATUS smb_posix_open(connection_struct *conn, wire_open_mode &= ~SMB_ACCMODE; - if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) { - create_disp = FILE_CREATE; - } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) { - create_disp = FILE_OVERWRITE_IF; - } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) { - create_disp = FILE_OPEN_IF; - } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) { - create_disp = FILE_OPEN; - } else { - DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n", - (unsigned int)wire_open_mode )); - return NT_STATUS_INVALID_PARAMETER; + /* First take care of O_CREAT|O_EXCL interactions. */ + switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) { + case (SMB_O_CREAT | SMB_O_EXCL): + /* File exists fail. File not exist create. */ + create_disp = FILE_CREATE; + break; + case SMB_O_CREAT: + /* File exists open. File not exist create. */ + create_disp = FILE_OPEN_IF; + break; + case 0: + /* File exists open. File not exist fail. */ + create_disp = FILE_OPEN; + break; + case SMB_O_EXCL: + /* O_EXCL on its own without O_CREAT is undefined. */ + default: + DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n", + (unsigned int)wire_open_mode )); + return NT_STATUS_INVALID_PARAMETER; + } + + /* Next factor in the effects of O_TRUNC. */ + wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL); + + if (wire_open_mode & SMB_O_TRUNC) { + switch (create_disp) { + case FILE_CREATE: + /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */ + /* Leave create_disp alone as + (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL) + */ + /* File exists fail. File not exist create. */ + break; + case FILE_OPEN_IF: + /* SMB_O_CREAT | SMB_O_TRUNC */ + /* File exists overwrite. File not exist create. */ + create_disp = FILE_OVERWRITE_IF; + break; + case FILE_OPEN: + /* SMB_O_TRUNC */ + /* File exists overwrite. File not exist fail. */ + create_disp = FILE_OVERWRITE; + break; + default: + /* Cannot get here. */ + smb_panic("smb_posix_open: logic error"); + return NT_STATUS_INVALID_PARAMETER; + } } raw_unixmode = IVAL(pdata,8); @@ -7350,6 +7367,15 @@ static NTSTATUS smb_posix_open(connection_struct *conn, mod_unixmode |= FILE_FLAG_NO_BUFFERING; } + if ((wire_open_mode & SMB_O_DIRECTORY) || + VALID_STAT_OF_DIR(smb_fname->st)) { + if (access_mask != SMB_O_RDONLY_MAPPING) { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } + create_options &= ~FILE_NON_DIRECTORY_FILE; + create_options |= FILE_DIRECTORY_FILE; + } + DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n", smb_fname_str_dbg(smb_fname), (unsigned int)wire_open_mode, @@ -7364,7 +7390,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn, (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */ FILE_SHARE_DELETE), create_disp, /* create_disposition*/ - FILE_NON_DIRECTORY_FILE, /* create_options */ + create_options, /* create_options */ mod_unixmode, /* file_attributes */ oplock_request, /* oplock_request */ 0, /* allocation_size */ @@ -8302,7 +8328,7 @@ static void call_trans2getdfsreferral(connection_struct *conn, return; } - SSVAL(req->inbuf, smb_flg2, + SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2, SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes); @@ -8351,7 +8377,7 @@ static void call_trans2ioctl(connection_struct *conn, SSVAL(pdata, 0, 0); } srvstr_push(pdata, req->flags2, pdata + 2, - global_myname(), 15, + lp_netbios_name(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ srvstr_push(pdata, req->flags2, pdata+18, lp_servicename(SNUM(conn)), 13, @@ -8433,7 +8459,7 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req, { if (get_Protocol() >= PROTOCOL_NT1) { req->flags2 |= 0x40; /* IS_LONG_NAME */ - SSVAL(req->inbuf,smb_flg2,req->flags2); + SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2); } if (conn->encrypt_level == Required && !req->encrypted) { @@ -8646,7 +8672,7 @@ void reply_trans2(struct smb_request *req) } } - if ((state = TALLOC_P(conn, struct trans_state)) == NULL) { + if ((state = talloc(conn, struct trans_state)) == NULL) { DEBUG(0, ("talloc failed\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtrans2); @@ -8792,7 +8818,7 @@ void reply_transs2(struct smb_request *req) START_PROFILE(SMBtranss2); - show_msg((char *)req->inbuf); + show_msg((const char *)req->inbuf); if (req->wct < 8) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index b554b36054..285b158a19 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -25,7 +25,6 @@ #include "libcli/security/security.h" #include "passdb/lookup_sid.h" #include "auth.h" -#include "ntdomain.h" /* what user is current? */ extern struct current_user current_user; @@ -183,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. ****************************************************************************/ @@ -390,7 +345,7 @@ bool change_to_user_by_session(connection_struct *conn, but modify the current_user entries. ****************************************************************************/ -bool change_to_root_user(void) +bool smbd_change_to_root_user(void) { set_root_sec_ctx(); @@ -409,14 +364,14 @@ bool change_to_root_user(void) user. Doesn't modify current_user. ****************************************************************************/ -bool become_authenticated_pipe_user(struct pipes_struct *p) +bool become_authenticated_pipe_user(struct auth_serversupplied_info *session_info) { if (!push_sec_ctx()) return False; - set_sec_ctx(p->session_info->utok.uid, p->session_info->utok.gid, - p->session_info->utok.ngroups, p->session_info->utok.groups, - p->session_info->security_token); + set_sec_ctx(session_info->utok.uid, session_info->utok.gid, + session_info->utok.ngroups, session_info->utok.groups, + session_info->security_token); return True; } @@ -486,7 +441,7 @@ static void pop_conn_ctx(void) restores the connection context. ****************************************************************************/ -void become_root(void) +void smbd_become_root(void) { /* * no good way to handle push_sec_ctx() failing without changing @@ -501,7 +456,7 @@ void become_root(void) /* Unbecome the root user */ -void unbecome_root(void) +void smbd_unbecome_root(void) { pop_sec_ctx(); pop_conn_ctx(); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 3b482e7f0c..7be3867267 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -183,7 +183,7 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object) DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object)); - handle = TALLOC_ZERO_P(conn, vfs_handle_struct); + handle = talloc_zero(conn, vfs_handle_struct); if (!handle) { DEBUG(0,("TALLOC_ZERO() failed!\n")); goto fail; @@ -795,7 +795,7 @@ int vfs_ChDir(connection_struct *conn, const char *path) char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) { - char s[PATH_MAX+1]; + char *current_dir = NULL; char *result = NULL; DATA_BLOB cache_value; struct file_id key; @@ -803,8 +803,6 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) struct smb_filename *smb_fname_full = NULL; NTSTATUS status; - *s = 0; - if (!lp_getwd_cache()) { goto nocache; } @@ -866,7 +864,8 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) * systems, or the not quite so bad getwd. */ - if (!SMB_VFS_GETWD(conn,s)) { + current_dir = SMB_VFS_GETWD(conn); + if (current_dir == NULL) { DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n", strerror(errno))); goto out; @@ -877,10 +876,11 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) memcache_add(smbd_memcache(), GETWD_CACHE, data_blob_const(&key, sizeof(key)), - data_blob_const(s, strlen(s)+1)); + data_blob_const(current_dir, + strlen(current_dir)+1)); } - result = talloc_strdup(ctx, s); + result = talloc_strdup(ctx, current_dir); if (result == NULL) { errno = ENOMEM; } @@ -888,6 +888,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) out: TALLOC_FREE(smb_fname_dot); TALLOC_FREE(smb_fname_full); + SAFE_FREE(current_dir); return result; } @@ -899,6 +900,8 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) { char *resolved_name = NULL; + bool allow_symlinks = true; + bool allow_widelinks = false; DEBUG(3,("check_reduced_name [%s] [%s]\n", fname, conn->connectpath)); @@ -973,9 +976,13 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) return NT_STATUS_OBJECT_NAME_INVALID; } - /* Check for widelinks allowed. */ - if (!lp_widelinks(SNUM(conn))) { + allow_widelinks = lp_widelinks(SNUM(conn)); + allow_symlinks = lp_symlinks(SNUM(conn)); + + /* Common widelinks and symlinks checks. */ + if (!allow_widelinks || !allow_symlinks) { const char *conn_rootdir; + size_t rootdir_len; conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname); if (conn_rootdir == NULL) { @@ -985,8 +992,9 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) return NT_STATUS_ACCESS_DENIED; } + rootdir_len = strlen(conn_rootdir); if (strncmp(conn_rootdir, resolved_name, - strlen(conn_rootdir)) != 0) { + rootdir_len) != 0) { DEBUG(2, ("check_reduced_name: Bad access " "attempt: %s is a symlink outside the " "share path\n", fname)); @@ -995,35 +1003,38 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) SAFE_FREE(resolved_name); return NT_STATUS_ACCESS_DENIED; } - } - /* Check if we are allowing users to follow symlinks */ - /* Patch from David Clerc <David.Clerc@cui.unige.ch> - University of Geneva */ + /* Extra checks if all symlinks are disallowed. */ + if (!allow_symlinks) { + /* fname can't have changed in resolved_path. */ + const char *p = &resolved_name[rootdir_len]; -#ifdef S_ISLNK - if (!lp_symlinks(SNUM(conn))) { - struct smb_filename *smb_fname = NULL; - NTSTATUS status; + /* *p can be '\0' if fname was "." */ + if (*p == '\0' && ISDOT(fname)) { + goto out; + } - status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, - NULL, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - SAFE_FREE(resolved_name); - return status; + if (*p != '/') { + DEBUG(2, ("check_reduced_name: logic error (%c) " + "in resolved_name: %s\n", + *p, + fname)); + SAFE_FREE(resolved_name); + return NT_STATUS_ACCESS_DENIED; + } + + p++; + if (strcmp(fname, p)!=0) { + DEBUG(2, ("check_reduced_name: Bad access " + "attempt: %s is a symlink\n", + fname)); + SAFE_FREE(resolved_name); + return NT_STATUS_ACCESS_DENIED; + } } + } - if ( (SMB_VFS_LSTAT(conn, smb_fname) != -1) && - (S_ISLNK(smb_fname->st.st_ex_mode)) ) { - SAFE_FREE(resolved_name); - DEBUG(3,("check_reduced_name: denied: file path name " - "%s is a symlink\n",resolved_name)); - TALLOC_FREE(smb_fname); - return NT_STATUS_ACCESS_DENIED; - } - TALLOC_FREE(smb_fname); - } -#endif + out: DEBUG(3,("check_reduced_name: %s reduced to %s\n", fname, resolved_name)); @@ -1164,7 +1175,7 @@ int smb_vfs_call_set_quota(struct vfs_handle_struct *handle, int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, - SHADOW_COPY_DATA *shadow_copy_data, + struct shadow_copy_data *shadow_copy_data, bool labels) { VFS_FIND(get_shadow_copy_data); @@ -1496,7 +1507,7 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid) } ZERO_STRUCT(local_fname); - local_fname.base_name = CONST_DISCARD(char *,final_component); + local_fname.base_name = discard_const_p(char, final_component); /* Must use lstat here. */ ret = SMB_VFS_LSTAT(fsp->conn, &local_fname); @@ -1543,10 +1554,10 @@ int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path) return handle->fns->chdir(handle, path); } -char *smb_vfs_call_getwd(struct vfs_handle_struct *handle, char *buf) +char *smb_vfs_call_getwd(struct vfs_handle_struct *handle) { VFS_FIND(getwd); - return handle->fns->getwd(handle, buf); + return handle->fns->getwd(handle); } int smb_vfs_call_ntimes(struct vfs_handle_struct *handle, |