From d93041e3363a6e0c6ebba63e6d8c92948be4f953 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 Nov 2008 19:11:40 -0800 Subject: Add reference to bug #4308 to remind me to add regression test to smbtorture. Jeremy. --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index cccf3087f7..97b87cc3a9 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3511,7 +3511,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); /* See here: http://www.codeproject.com/KB/winsdk/accessctrl2.aspx - * for details. JRA. + * for details and also the log trace in bug #4308. JRA. */ if ((security_info_sent & DACL_SECURITY_INFORMATION) && -- cgit From 24c598b1b95742961d43ff5bd61831405b561dfe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Nov 2008 01:40:21 -0800 Subject: Don't call FSET_NT_ACL on file create if there's no SD to set. Leave the default ACL in place. Jeremy. --- source3/smbd/open.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 480352beda..3fd0d1a03a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2923,7 +2923,12 @@ NTSTATUS create_file_unixpath(connection_struct *conn, security_acl_map_generic(sd->dacl, &file_generic_mapping); security_acl_map_generic(sd->sacl, &file_generic_mapping); - status = SMB_VFS_FSET_NT_ACL(fsp, sec_info_sent, sd); + if (sec_info_sent & (OWNER_SECURITY_INFORMATION| + GROUP_SECURITY_INFORMATION| + DACL_SECURITY_INFORMATION| + SACL_SECURITY_INFORMATION)) { + status = SMB_VFS_FSET_NT_ACL(fsp, sec_info_sent, sd); + } fsp->access_mask = saved_access_mask; -- cgit From 7522ef15aca2429ef57c75d8297dd8121e79c9da Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Nov 2008 01:45:40 -0800 Subject: Final fix to make us pass NULL SD test in RAW-ACLs. Not sure if this is 100% right. Only inheritance left to fix. Jeremy. --- source3/smbd/nttrans.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f711b588c5..50a3aea856 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -725,6 +725,9 @@ static NTSTATUS set_sd(files_struct *fsp, uint8 *data, uint32 sd_len, if (psd->sacl==0) { security_info_sent &= ~SACL_SECURITY_INFORMATION; } + if (security_info_sent & DACL_SECURITY_INFORMATION) { + psd->type |= SEC_DESC_DACL_PRESENT; + } if (psd->dacl==0) { security_info_sent &= ~DACL_SECURITY_INFORMATION; } -- cgit From 8b4b5c3a92be83e99d9177b04f0da56f610025de Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Nov 2008 18:53:00 -0800 Subject: Add wrapper str_list_make_v3() to replace the old S3 behavior of str_list_make(). From Dan Sledz : In samba 3.2 passing NULL or an empty string returned NULL. In master, it now returns a list of length 1 with the first string set to NULL (an empty list). Jeremy. --- source3/smbd/map_username.c | 2 +- source3/smbd/password.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c index a8899dd538..f549f0c9f3 100644 --- a/source3/smbd/map_username.c +++ b/source3/smbd/map_username.c @@ -178,7 +178,7 @@ bool map_username(fstring user) /* skip lines like 'user = ' */ - dosuserlist = str_list_make(talloc_tos(), dosname, NULL); + dosuserlist = str_list_make_v3(talloc_tos(), dosname, NULL); if (!dosuserlist) { DEBUG(0,("Bad username map entry. Unable to build user list. Ignoring.\n")); continue; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 88e7b766be..84b40f28cc 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -576,7 +576,7 @@ static bool user_ok(const char *user, int snum) TALLOC_FREE(valid); if (ret && lp_onlyuser(snum)) { - char **user_list = str_list_make( + char **user_list = str_list_make_v3( talloc_tos(), lp_username(snum), NULL); if (user_list && str_list_substitute(user_list, "%S", -- cgit From 7ae625345536572aa946f0715542a5cf2dbc2169 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Thu, 6 Nov 2008 20:40:20 -0800 Subject: Convert to use VFS layer. --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 97b87cc3a9..7ca2ed787b 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4301,7 +4301,7 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) finfo.fh->fd = -1; finfo.fsp_name = CONST_DISCARD(char *,fname); - if (!NT_STATUS_IS_OK(posix_fget_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd))) { + if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo, DACL_SECURITY_INFORMATION, &psd))) { DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n")); conn_free_internal( conn ); return NULL; -- cgit From 8962be69c700224983af4effd2cd086f7f5800b0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Nov 2008 20:48:13 -0800 Subject: Make us clean under valgrind --leak-check=full by using talloc_autofree_context() instead of NULL. Remove the code in memcache that does a TALLOC_FREE on stored pointers. That's a disaster waiting to happen. If you're storing talloc'ed pointers, you can't know their lifecycle and they should be deleted when their parent context is deleted, so freeing them at some arbitrary point later will be a double-free. Jeremy. --- source3/smbd/server.c | 6 +++--- source3/smbd/uid.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7583da65a5..fff05a3aac 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -80,7 +80,7 @@ struct event_context *smbd_event_context(void) { static struct event_context *ctx; - if (!ctx && !(ctx = event_context_init(NULL))) { + if (!ctx && !(ctx = event_context_init(talloc_autofree_context()))) { smb_panic("Could not init smbd event context"); } return ctx; @@ -91,7 +91,7 @@ struct messaging_context *smbd_messaging_context(void) static struct messaging_context *ctx; if (ctx == NULL) { - ctx = messaging_init(NULL, server_id_self(), + ctx = messaging_init(talloc_autofree_context(), server_id_self(), smbd_event_context()); } if (ctx == NULL) { @@ -105,7 +105,7 @@ struct memcache *smbd_memcache(void) static struct memcache *cache; if (!cache - && !(cache = memcache_init(NULL, + && !(cache = memcache_init(talloc_autofree_context(), lp_max_stat_cache_size()*1024))) { smb_panic("Could not init smbd memcache"); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 8998f6a371..045de6f2d3 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -32,7 +32,7 @@ bool change_to_guest(void) if (!pass) { /* Don't need to free() this as its stored in a static */ - pass = getpwnam_alloc(NULL, lp_guestaccount()); + pass = getpwnam_alloc(talloc_autofree_context(), lp_guestaccount()); if (!pass) return(False); } -- cgit From 87d4138d095bd6554ded80a94fb706bb754ae4c6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Nov 2008 22:04:58 +0100 Subject: Converting notify.c to store a request, not an inbuf --- source3/smbd/notify.c | 83 +++++++++++++++++--------------------------------- source3/smbd/nttrans.c | 3 +- 2 files changed, 30 insertions(+), 56 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index b2d0f20f89..5a517654bf 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -24,7 +24,7 @@ struct notify_change_request { struct notify_change_request *prev, *next; struct files_struct *fsp; /* backpointer for cancel by mid */ - uint8 request_buf[smb_size]; + struct smb_request *req; uint32 filter; uint32 max_param; struct notify_mid_map *mid_map; @@ -133,40 +133,33 @@ static bool notify_marshall_changes(int num_changes, *****************************************************************************/ static void change_notify_reply_packet(connection_struct *conn, - const uint8 *request_buf, + struct smb_request *req, NTSTATUS error_code) { - char outbuf[smb_size+38]; + reply_outbuf(req, 18, 0); - memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common((char *)request_buf, outbuf); - - ERROR_NT(error_code); - - /* - * Seems NT needs a transact command with an error code - * in it. This is a longer packet than a simple error. - */ - srv_set_message(outbuf,18,0,False); + if (!NT_STATUS_IS_OK(error_code)) { + error_packet_set((char *)req->outbuf, 0, 0, error_code, + __LINE__,__FILE__); + } - show_msg(outbuf); - if (!srv_send_smb(smbd_server_fd(), - outbuf, - IS_CONN_ENCRYPTED(conn))) + show_msg((char *)req->outbuf); + if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + req->encrypted)) { exit_server_cleanly("change_notify_reply_packet: srv_send_smb " "failed."); + } + TALLOC_FREE(req->outbuf); } void change_notify_reply(connection_struct *conn, - const uint8 *request_buf, uint32 max_param, + struct smb_request *req, uint32 max_param, struct notify_change_buf *notify_buf) { prs_struct ps; - struct smb_request *req = NULL; - uint8 tmp_request[smb_size]; if (notify_buf->num_changes == -1) { - change_notify_reply_packet(conn, request_buf, NT_STATUS_OK); + change_notify_reply_packet(conn, req, NT_STATUS_OK); notify_buf->num_changes = 0; return; } @@ -179,32 +172,14 @@ void change_notify_reply(connection_struct *conn, * We exceed what the client is willing to accept. Send * nothing. */ - change_notify_reply_packet(conn, request_buf, NT_STATUS_OK); - goto done; - } - - if (!(req = talloc(talloc_tos(), struct smb_request))) { - change_notify_reply_packet(conn, request_buf, NT_STATUS_NO_MEMORY); + change_notify_reply_packet(conn, req, NT_STATUS_OK); goto done; } - memcpy(tmp_request, request_buf, smb_size); - - /* - * We're only interested in the header fields here - */ - - smb_setlen((char *)tmp_request, smb_size); - SCVAL(tmp_request, smb_wct, 0); - - init_smb_request(req, tmp_request,0, conn->encrypted_tid); - req->inbuf = tmp_request; - send_nt_replies(conn, req, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0); done: - TALLOC_FREE(req); prs_mem_free(&ps); TALLOC_FREE(notify_buf->changes); @@ -252,7 +227,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return status; } -NTSTATUS change_notify_add_request(const struct smb_request *req, +NTSTATUS change_notify_add_request(struct smb_request *req, uint32 max_param, uint32 filter, bool recursive, struct files_struct *fsp) @@ -263,16 +238,16 @@ NTSTATUS change_notify_add_request(const struct smb_request *req, DEBUG(10, ("change_notify_add_request: Adding request for %s: " "max_param = %d\n", fsp->fsp_name, (int)max_param)); - if (!(request = SMB_MALLOC_P(struct notify_change_request)) - || !(map = SMB_MALLOC_P(struct notify_mid_map))) { - SAFE_FREE(request); + if (!(request = talloc(NULL, struct notify_change_request)) + || !(map = talloc(request, struct notify_mid_map))) { + TALLOC_FREE(request); return NT_STATUS_NO_MEMORY; } request->mid_map = map; map->req = request; - memcpy(request->request_buf, req->inbuf, sizeof(request->request_buf)); + request->req = talloc_move(request, &req); request->max_param = max_param; request->filter = filter; request->fsp = fsp; @@ -281,11 +256,11 @@ NTSTATUS change_notify_add_request(const struct smb_request *req, DLIST_ADD_END(fsp->notify->requests, request, struct notify_change_request *); - map->mid = SVAL(req->inbuf, smb_mid); + map->mid = request->req->mid; DLIST_ADD(notify_changes_by_mid, map); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(req->inbuf,smb_mid)); + srv_defer_sign_response(request->req->mid); return NT_STATUS_OK; } @@ -315,9 +290,7 @@ static void change_notify_remove_request(struct notify_change_request *remove_re DLIST_REMOVE(fsp->notify->requests, req); DLIST_REMOVE(notify_changes_by_mid, req->mid_map); - SAFE_FREE(req->mid_map); - TALLOC_FREE(req->backend_data); - SAFE_FREE(req); + TALLOC_FREE(req); } /**************************************************************************** @@ -338,8 +311,8 @@ void remove_pending_change_notify_requests_by_mid(uint16 mid) return; } - change_notify_reply_packet(map->req->fsp->conn, - map->req->request_buf, NT_STATUS_CANCELLED); + change_notify_reply_packet(map->req->fsp->conn, map->req->req, + NT_STATUS_CANCELLED); change_notify_remove_request(map->req); } @@ -355,8 +328,8 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, } while (fsp->notify->requests != NULL) { - change_notify_reply_packet(fsp->conn, - fsp->notify->requests->request_buf, status); + change_notify_reply_packet( + fsp->conn, fsp->notify->requests->req, status); change_notify_remove_request(fsp->notify->requests); } } @@ -450,7 +423,7 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) */ change_notify_reply(fsp->conn, - fsp->notify->requests->request_buf, + fsp->notify->requests->req, fsp->notify->requests->max_param, fsp->notify); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 50a3aea856..565f2cbb5f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1443,7 +1443,8 @@ static void call_nt_transact_notify_change(connection_struct *conn, * here. */ - change_notify_reply(fsp->conn, req->inbuf, max_param_count, fsp->notify); + change_notify_reply(fsp->conn, req, max_param_count, + fsp->notify); /* * change_notify_reply() above has independently sent its -- cgit From 5e2956557b06b5b55dc8810b51bdbcf3e7f03c98 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 5 Nov 2008 19:16:06 +0100 Subject: Remove the change to the user context in process_blocking_lock_queue() --- source3/smbd/blocking.c | 84 +++++-------------------------------------------- 1 file changed, 8 insertions(+), 76 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 555033b7df..87ae3ca272 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -666,78 +666,9 @@ static void process_blocking_lock_queue(void) */ for (blr = blocking_lock_queue; blr; blr = next) { - connection_struct *conn = NULL; - uint16 vuid; - files_struct *fsp = NULL; next = blr->next; - /* - * Ensure we don't have any old chain_fsp values - * sitting around.... - */ - chain_size = 0; - fsp = blr->fsp; - - conn = conn_find(blr->req->tid); - vuid = (lp_security() == SEC_SHARE) - ? UID_FIELD_INVALID : blr->req->vuid; - - DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", - fsp->fnum, fsp->fsp_name )); - - if(!change_to_user(conn,vuid)) { - struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); - - /* - * Remove the entry and return an error to the client. - */ - - if (br_lck) { - brl_lock_cancel(br_lck, - blr->lock_pid, - procid_self(), - blr->offset, - blr->count, - blr->lock_flav); - TALLOC_FREE(br_lck); - } - - DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", - vuid )); - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); - DLIST_REMOVE(blocking_lock_queue, blr); - TALLOC_FREE(blr); - recalc_timeout = True; - continue; - } - - if(!set_current_service(conn,SVAL(blr->req->inbuf,smb_flg),True)) { - struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); - - /* - * Remove the entry and return an error to the client. - */ - - if (br_lck) { - brl_lock_cancel(br_lck, - blr->lock_pid, - procid_self(), - blr->offset, - blr->count, - blr->lock_flav); - TALLOC_FREE(br_lck); - } - - DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); - DLIST_REMOVE(blocking_lock_queue, blr); - TALLOC_FREE(blr); - recalc_timeout = True; - change_to_root_user(); - continue; - } - /* * Go through the remaining locks and try and obtain them. * The call returns True if all locks were obtained successfully @@ -745,7 +676,8 @@ static void process_blocking_lock_queue(void) */ if(blocking_lock_record_process(blr)) { - struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); + struct byte_range_lock *br_lck = brl_get_locks( + talloc_tos(), blr->fsp); if (br_lck) { brl_lock_cancel(br_lck, @@ -760,19 +692,17 @@ static void process_blocking_lock_queue(void) DLIST_REMOVE(blocking_lock_queue, blr); TALLOC_FREE(blr); recalc_timeout = True; - change_to_root_user(); continue; } - change_to_root_user(); - /* * We couldn't get the locks for this record on the list. * If the time has expired, return a lock error. */ if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) { - struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); + struct byte_range_lock *br_lck = brl_get_locks( + talloc_tos(), blr->fsp); /* * Lock expired - throw away all previously @@ -780,8 +710,10 @@ static void process_blocking_lock_queue(void) */ if (br_lck) { - DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", - fsp->fnum, fsp->fsp_name )); + DEBUG(5,("process_blocking_lock_queue: " + "pending lock fnum = %d for file %s " + "timed out.\n", blr->fsp->fnum, + blr->fsp->fsp_name )); brl_lock_cancel(br_lck, blr->lock_pid, -- cgit From 52958ea115ab3d1d8cebaad47b5ffff7fc86a4cd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 5 Nov 2008 19:19:17 +0100 Subject: Remove a direct inbuf reference (should have been removed with 8987641d...) --- source3/smbd/aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index fd553c3fc4..8beed0744c 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -506,7 +506,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) ERROR_BOTH(map_nt_error_from_unix(ret), ERRHRD, ERRdiskfull); srv_set_message(outbuf,0,0,true); } else { - bool write_through = BITSETW(aio_ex->req->inbuf+smb_vwv7,0); + bool write_through = BITSETW(aio_ex->req->vwv+7,0); NTSTATUS status; SSVAL(outbuf,smb_vwv2,nwritten); -- cgit From 807ad174b288e4c3d36ed02e5ef02cd7a848ce0e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 6 Nov 2008 12:14:08 +0100 Subject: Remove a direct inbuf reference from reply_nttrans() --- source3/smbd/nttrans.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 565f2cbb5f..c7a8bf7650 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2689,8 +2689,7 @@ void reply_nttrans(struct smb_request *req) goto bad_param; } - memcpy( state->setup, &req->inbuf[smb_nt_SetupStart], - state->setup_count); + memcpy(state->setup, req->vwv+19, state->setup_count); dump_data(10, (uint8 *)state->setup, state->setup_count); } -- cgit From 8637dd12325369e0056d77924cac577a67f2a0ab Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 6 Nov 2008 20:16:04 +0100 Subject: change CHECK_READ to use smb_request instead of inbuf --- source3/smbd/reply.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 377ba4e530..be39fd464d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2894,7 +2894,7 @@ void reply_lockread(struct smb_request *req) return; } - if (!CHECK_READ(fsp,req->inbuf)) { + if (!CHECK_READ(fsp,req)) { reply_doserror(req, ERRDOS, ERRbadaccess); END_PROFILE(SMBlockread); return; @@ -3002,7 +3002,7 @@ void reply_read(struct smb_request *req) return; } - if (!CHECK_READ(fsp,req->inbuf)) { + if (!CHECK_READ(fsp,req)) { reply_doserror(req, ERRDOS, ERRbadaccess); END_PROFILE(SMBread); return; @@ -3255,7 +3255,7 @@ void reply_read_and_X(struct smb_request *req) return; } - if (!CHECK_READ(fsp,req->inbuf)) { + if (!CHECK_READ(fsp,req)) { reply_doserror(req, ERRDOS,ERRbadaccess); END_PROFILE(SMBreadX); return; -- cgit From 7a35506bb87fd784a4a7a5b81c2d2ab5c32b233b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Nov 2008 12:29:24 +0100 Subject: Remove direct inbuf refs from send_trans_reply --- source3/smbd/ipc.c | 72 ++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index b9460e5211..c7a44270f5 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -91,7 +91,6 @@ void send_trans_reply(connection_struct *conn, int tot_data_sent = 0; int tot_param_sent = 0; int align; - char *outbuf; int ldata = rdata ? rdata_len : 0; int lparam = rparam ? rparam_len : 0; @@ -104,38 +103,37 @@ void send_trans_reply(connection_struct *conn, align = ((this_lparam)%4); - if (!create_outbuf(talloc_tos(), (char *)req->inbuf, &outbuf, - 10, 1+align+this_ldata+this_lparam)) { - smb_panic("could not allocate outbuf"); - } + reply_outbuf(req, 10, 1+align+this_ldata+this_lparam); - copy_trans_params_and_data(outbuf, align, + copy_trans_params_and_data((char *)req->outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); - SSVAL(outbuf,smb_vwv0,lparam); - SSVAL(outbuf,smb_vwv1,ldata); - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); - SSVAL(outbuf,smb_vwv5,0); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align, - outbuf)); - SSVAL(outbuf,smb_vwv8,0); - SSVAL(outbuf,smb_vwv9,0); + SSVAL(req->outbuf,smb_vwv0,lparam); + SSVAL(req->outbuf,smb_vwv1,ldata); + SSVAL(req->outbuf,smb_vwv3,this_lparam); + SSVAL(req->outbuf,smb_vwv4, + smb_offset(smb_buf(req->outbuf)+1, req->outbuf)); + SSVAL(req->outbuf,smb_vwv5,0); + SSVAL(req->outbuf,smb_vwv6,this_ldata); + SSVAL(req->outbuf,smb_vwv7, + smb_offset(smb_buf(req->outbuf)+1+this_lparam+align, + req->outbuf)); + SSVAL(req->outbuf,smb_vwv8,0); + SSVAL(req->outbuf,smb_vwv9,0); if (buffer_too_large) { - error_packet_set((char *)outbuf, ERRDOS, ERRmoredata, + error_packet_set((char *)req->outbuf, ERRDOS, ERRmoredata, STATUS_BUFFER_OVERFLOW, __LINE__, __FILE__); } - show_msg(outbuf); - if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, + show_msg((char *)req->outbuf); + if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, IS_CONN_ENCRYPTED(conn))) { exit_server_cleanly("send_trans_reply: srv_send_smb failed."); } - TALLOC_FREE(outbuf); + TALLOC_FREE(req->outbuf); tot_data_sent = this_ldata; tot_param_sent = this_lparam; @@ -155,39 +153,39 @@ void send_trans_reply(connection_struct *conn, align = (this_lparam%4); - if (!create_outbuf(talloc_tos(), (char *)req->inbuf, &outbuf, - 10, 1+align+this_ldata+this_lparam)) { - smb_panic("could not allocate outbuf"); - } + reply_outbuf(req, 10, 1+align+this_ldata+this_lparam); - copy_trans_params_and_data(outbuf, align, + copy_trans_params_and_data((char *)req->outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); - SSVAL(outbuf,smb_vwv5,tot_param_sent); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7, - smb_offset(smb_buf(outbuf)+1+this_lparam+align, outbuf)); - SSVAL(outbuf,smb_vwv8,tot_data_sent); - SSVAL(outbuf,smb_vwv9,0); + SSVAL(req->outbuf,smb_vwv3,this_lparam); + SSVAL(req->outbuf,smb_vwv4, + smb_offset(smb_buf(req->outbuf)+1,req->outbuf)); + SSVAL(req->outbuf,smb_vwv5,tot_param_sent); + SSVAL(req->outbuf,smb_vwv6,this_ldata); + SSVAL(req->outbuf,smb_vwv7, + smb_offset(smb_buf(req->outbuf)+1+this_lparam+align, + req->outbuf)); + SSVAL(req->outbuf,smb_vwv8,tot_data_sent); + SSVAL(req->outbuf,smb_vwv9,0); if (buffer_too_large) { - error_packet_set(outbuf, ERRDOS, ERRmoredata, + error_packet_set((char *)req->outbuf, + ERRDOS, ERRmoredata, STATUS_BUFFER_OVERFLOW, __LINE__, __FILE__); } - show_msg(outbuf); - if (!srv_send_smb(smbd_server_fd(), outbuf, + show_msg((char *)req->outbuf); + if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, IS_CONN_ENCRYPTED(conn))) exit_server_cleanly("send_trans_reply: srv_send_smb " "failed."); tot_data_sent += this_ldata; tot_param_sent += this_lparam; - TALLOC_FREE(outbuf); + TALLOC_FREE(req->outbuf); } } -- cgit From 8315677ca3ca9eed62fe6e24bac333b9b5dc763b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Nov 2008 20:38:05 +0100 Subject: Do not write into inbuf for the transs request Instead, fix up the outbuf in send_xx_reply. In those routines, we know what we are returning. --- source3/smbd/blocking.c | 1 - source3/smbd/ipc.c | 18 ++++++++++++------ source3/smbd/nttrans.c | 11 +++++------ source3/smbd/trans2.c | 12 ++++++------ 4 files changed, 23 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 87ae3ca272..2237a89ace 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -505,7 +505,6 @@ static bool process_trans2(blocking_lock_record *blr) /* We finally got the lock, return success. */ - SCVAL(blr->req->inbuf, smb_com, SMBtrans2); SSVAL(params,0,0); /* Fake up max_data_bytes here - we know it fits. */ send_trans2_replies(blr->fsp->conn, blr->req, params, 2, NULL, 0, 0xffff); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c7a44270f5..26a4212ec9 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -105,6 +105,12 @@ void send_trans_reply(connection_struct *conn, reply_outbuf(req, 10, 1+align+this_ldata+this_lparam); + /* + * We might have SMBtranss in req which was transferred to the outbuf, + * fix that. + */ + SCVAL(req->outbuf, smb_com, SMBtrans); + copy_trans_params_and_data((char *)req->outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); @@ -155,6 +161,12 @@ void send_trans_reply(connection_struct *conn, reply_outbuf(req, 10, 1+align+this_ldata+this_lparam); + /* + * We might have SMBtranss in req which was transferred to the + * outbuf, fix that. + */ + SCVAL(req->outbuf, smb_com, SMBtrans); + copy_trans_params_and_data((char *)req->outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); @@ -774,12 +786,6 @@ void reply_transs(struct smb_request *req) return; } - /* - * construct_reply_common will copy smb_com from inbuf to - * outbuf. SMBtranss is wrong here. - */ - SCVAL(req->inbuf,smb_com,SMBtrans); - handle_trans(conn, req, state); DLIST_REMOVE(conn->pending_trans, state); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c7a8bf7650..1a13d962f0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -119,6 +119,11 @@ void send_nt_replies(connection_struct *conn, total_sent_thistime + alignment_offset + data_alignment_offset); + /* + * We might have had SMBnttranss in req->inbuf, fix that. + */ + SCVAL(req->outbuf, smb_com, SMBnttrans); + /* * Set total params and data to be sent. */ @@ -2829,12 +2834,6 @@ void reply_nttranss(struct smb_request *req) return; } - /* - * construct_reply_common will copy smb_com from inbuf to - * outbuf. SMBnttranss is wrong here. - */ - SCVAL(req->inbuf,smb_com,SMBnttrans); - handle_nttrans(conn, state, req); DLIST_REMOVE(conn->pending_trans, state); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d0e3a68e8a..c385c6ccb1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -768,6 +768,12 @@ void send_trans2_replies(connection_struct *conn, reply_outbuf(req, 10, total_sent_thistime + alignment_offset + data_alignment_offset); + /* + * We might have SMBtrans2s in req which was transferred to + * the outbuf, fix that. + */ + SCVAL(req->outbuf, smb_com, SMBtrans2); + /* Set total params and data to be sent */ SSVAL(req->outbuf,smb_tprcnt,paramsize); SSVAL(req->outbuf,smb_tdrcnt,datasize); @@ -7822,12 +7828,6 @@ void reply_transs2(struct smb_request *req) return; } - /* - * construct_reply_common will copy smb_com from inbuf to - * outbuf. SMBtranss2 is wrong here. - */ - SCVAL(req->inbuf,smb_com,SMBtrans2); - handle_trans2(conn, req, state); DLIST_REMOVE(conn->pending_trans, state); -- cgit From 5a33e906f651ea84ec909fd6453e13a9489bd391 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Nov 2008 21:02:11 +0100 Subject: Make "construct_reply_common" static --- source3/smbd/process.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7931fbebab..b3cd2f26c8 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -37,6 +37,8 @@ SIG_ATOMIC_T got_sig_term = 0; extern bool global_machine_password_needs_changing; extern int max_send; +static void construct_reply_common(const char *inbuf, char *outbuf); + /* Accessor function for smb_read_error for smbd functions. */ /**************************************************************************** @@ -1590,7 +1592,7 @@ void remove_from_common_flags2(uint32 v) common_flags2 &= ~v; } -void construct_reply_common(const char *inbuf, char *outbuf) +static void construct_reply_common(const char *inbuf, char *outbuf) { srv_set_message(outbuf,0,0,false); -- cgit From 0baca66589d72acf7b3d6edf7c7d21fa17f98915 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Nov 2008 14:21:09 -0800 Subject: Fix bug 5889. "delete veto files = no" seems to break. Jeremy. --- source3/smbd/reply.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index be39fd464d..c363ed5609 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4989,8 +4989,16 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, } } - /* We only have veto files/directories. Recursive delete. */ + /* We only have veto files/directories. + * Are we allowed to delete them ? */ + if(!lp_recursive_veto_delete(SNUM(conn))) { + TALLOC_FREE(dir_hnd); + errno = ENOTEMPTY; + goto err; + } + + /* Do a recursive delete. */ RewindDir(dir_hnd,&dirpos); while ((dname = ReadDirName(dir_hnd,&dirpos))) { char *fullname = NULL; @@ -5016,9 +5024,8 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, break; } if(st.st_mode & S_IFDIR) { - if(lp_recursive_veto_delete(SNUM(conn))) { - if(!recursive_rmdir(ctx, conn, fullname)) - break; + if(!recursive_rmdir(ctx, conn, fullname)) { + break; } if(SMB_VFS_RMDIR(conn,fullname) != 0) { break; -- cgit From d38bffd4126062b92384f0930196059441a2d765 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Wed, 5 Nov 2008 13:40:03 -0800 Subject: s3: Add support for storing dos attributes as st_flags in the stat struct. Some filesystems have support for storing dos attributes directly in the inode's st_flags and accessing them through the stat struct. This patch: - Adds a configure check to see if the special flags are available. - Implements getting and setting dos attributes in the stat struct and inode, respectively. This will not change the existing functionality of any system that doesn't have the special flags available. --- source3/smbd/dosmode.c | 160 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 147 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 784b36d9bd..954cd5a4d2 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -30,6 +30,17 @@ static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf) return 0; } +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; +#endif +#endif + return 0; +} + /**************************************************************************** Change a dos mode to a unix mode. Base permission for files: @@ -159,13 +170,7 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_ result = aDIR | (result & aRONLY); result |= set_sparse_flag(sbuf); - -#ifdef S_ISLNK -#if LINKS_READ_ONLY - if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) - result |= aRONLY; -#endif -#endif + result |= set_link_read_only_flag(sbuf); DEBUG(8,("dos_mode_from_sbuf returning ")); @@ -343,6 +348,113 @@ uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT return(result); } +#ifdef HAVE_STAT_DOS_FLAGS +/**************************************************************************** + Convert dos attributes (FILE_ATTRIBUTE_*) to dos stat flags (UF_*) +****************************************************************************/ + +static int dos_attributes_to_stat_dos_flags(uint32_t dosmode) +{ + uint32_t dos_stat_flags = 0; + + if (dosmode & aARCH) + dos_stat_flags |= UF_DOS_ARCHIVE; + if (dosmode & aHIDDEN) + dos_stat_flags |= UF_DOS_HIDDEN; + if (dosmode & aRONLY) + dos_stat_flags |= UF_DOS_RO; + if (dosmode & aSYSTEM) + dos_stat_flags |= UF_DOS_SYSTEM; + if (dosmode & FILE_ATTRIBUTE_NONINDEXED) + dos_stat_flags |= UF_DOS_NOINDEX; + + return dos_stat_flags; +} + +/**************************************************************************** + Gets DOS attributes, accessed via st_flags in the stat struct. +****************************************************************************/ + +static bool get_stat_dos_flags(connection_struct *conn, + const char *fname, + const SMB_STRUCT_STAT *sbuf, + uint32_t *dosmode) +{ + SMB_ASSERT(sbuf && VALID_STAT(*sbuf)); + SMB_ASSERT(dosmode); + + if (!lp_store_dos_attributes(SNUM(conn))) { + return false; + } + + DEBUG(5, ("Getting stat dos attributes for %s.\n", fname)); + + if (sbuf->st_flags & UF_DOS_ARCHIVE) + *dosmode |= aARCH; + if (sbuf->st_flags & UF_DOS_HIDDEN) + *dosmode |= aHIDDEN; + if (sbuf->st_flags & UF_DOS_RO) + *dosmode |= aRONLY; + if (sbuf->st_flags & UF_DOS_SYSTEM) + *dosmode |= aSYSTEM; + if (sbuf->st_flags & UF_DOS_NOINDEX) + *dosmode |= FILE_ATTRIBUTE_NONINDEXED; + if (S_ISDIR(sbuf->st_mode)) + *dosmode |= aDIR; + + *dosmode |= set_sparse_flag(sbuf); + *dosmode |= set_link_read_only_flag(sbuf); + + return true; +} + +/**************************************************************************** + Sets DOS attributes, stored in st_flags of the inode. +****************************************************************************/ + +static bool set_stat_dos_flags(connection_struct *conn, + const char *fname, + SMB_STRUCT_STAT *sbuf, + uint32_t dosmode, + bool *attributes_changed) +{ + uint32_t new_flags = 0; + int error = 0; + + SMB_ASSERT(sbuf && VALID_STAT(*sbuf)); + SMB_ASSERT(attributes_changed); + + *attributes_changed = false; + + if (!lp_store_dos_attributes(SNUM(conn))) { + return false; + } + + DEBUG(5, ("Setting stat dos attributes for %s.\n", fname)); + + new_flags = (sbuf->st_flags & ~UF_DOS_FLAGS) | + dos_attributes_to_stat_dos_flags(dosmode); + + /* Return early if no flags changed. */ + if (new_flags == sbuf->st_flags) + return true; + + DEBUG(5, ("Setting stat dos attributes=0x%x, prev=0x%x\n", new_flags, + sbuf->st_flags)); + + /* Set new flags with chflags. */ + error = SMB_VFS_CHFLAGS(conn, fname, new_flags); + if (error) { + DEBUG(0, ("Failed setting new stat dos attributes (0x%x) on " + "file %s! errno=%d\n", new_flags, fname, errno)); + return false; + } + + *attributes_changed = true; + return true; +} +#endif /* HAVE_STAT_DOS_FLAGS */ + /**************************************************************************** Change a unix mode to a dos mode. ****************************************************************************/ @@ -350,7 +462,7 @@ uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) { uint32 result = 0; - bool offline; + bool offline, used_stat_dos_flags = false; DEBUG(8,("dos_mode: %s\n", path)); @@ -373,11 +485,16 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) } } - /* Get the DOS attributes from an EA by preference. */ - if (get_ea_dos_attribute(conn, path, sbuf, &result)) { - result |= set_sparse_flag(sbuf); - } else { - result |= dos_mode_from_sbuf(conn, path, sbuf); +#ifdef HAVE_STAT_DOS_FLAGS + used_stat_dos_flags = get_stat_dos_flags(conn, path, sbuf, &result); +#endif + if (!used_stat_dos_flags) { + /* Get the DOS attributes from an EA by preference. */ + if (get_ea_dos_attribute(conn, path, sbuf, &result)) { + result |= set_sparse_flag(sbuf); + } else { + result |= dos_mode_from_sbuf(conn, path, sbuf); + } } @@ -468,6 +585,23 @@ int file_set_dosmode(connection_struct *conn, const char *fname, return(0); } +#ifdef HAVE_STAT_DOS_FLAGS + { + bool attributes_changed; + + if (set_stat_dos_flags(conn, fname, st, dosmode, + &attributes_changed)) + { + if (!newfile && attributes_changed) { + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + } + st->st_mode = unixmode; + return 0; + } + } +#endif + /* Store the DOS attributes in an EA by preference. */ if (set_ea_dos_attribute(conn, fname, st, dosmode)) { if (!newfile) { -- cgit From 6f0be6c5d580ea751b28a0166b4454a0ef333dc2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Nov 2008 19:27:17 -0800 Subject: Pretty print out SD's on get/set. Jeremy. --- source3/smbd/nttrans.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1a13d962f0..caace5197c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -741,6 +741,11 @@ static NTSTATUS set_sd(files_struct *fsp, uint8 *data, uint32 sd_len, security_acl_map_generic(psd->dacl, &file_generic_mapping); security_acl_map_generic(psd->sacl, &file_generic_mapping); + if (DEBUGLEVEL >= 10) { + DEBUG(10,("set_sd for file %s\n", fsp->fsp_name )); + NDR_PRINT_DEBUG(security_descriptor, psd); + } + status = SMB_VFS_FSET_NT_ACL(fsp, security_info_sent, psd); TALLOC_FREE(psd); @@ -1601,6 +1606,11 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size)); + if (DEBUGLEVEL >= 10) { + DEBUG(10,("call_nt_transact_query_security_desc for file %s\n", fsp->fsp_name ) + NDR_PRINT_DEBUG(security_descriptor, psd); + } + SIVAL(params,0,(uint32)sd_size); if (max_data_count < sd_size) { -- cgit From 5e25f5f4f2b5b8dfd31206ebdc295c00870effe9 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Wed, 12 Nov 2008 21:24:00 -0800 Subject: Fix build break --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index caace5197c..52c16e2ac6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1607,7 +1607,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size)); if (DEBUGLEVEL >= 10) { - DEBUG(10,("call_nt_transact_query_security_desc for file %s\n", fsp->fsp_name ) + DEBUG(10,("call_nt_transact_query_security_desc for file %s\n", fsp->fsp_name)); NDR_PRINT_DEBUG(security_descriptor, psd); } -- cgit From d8df43e65d507710de72c6743f43127ad14019fc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Nov 2008 14:13:20 -0800 Subject: Fix bug #5900 reported by monyo@samba.gr.jp - vfs_readonly.so does not work. Jeremy. --- source3/smbd/share_access.c | 6 ++++-- source3/smbd/uid.c | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index f5f79c86e5..9dbacc2998 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -252,9 +252,11 @@ bool user_ok_token(const char *username, const char *domain, bool is_share_read_only_for_token(const char *username, const char *domain, - struct nt_user_token *token, int snum) + struct nt_user_token *token, + connection_struct *conn) { - bool result = lp_readonly(snum); + int snum = SNUM(conn); + bool result = conn->read_only; if (lp_readlist(snum) != NULL) { if (token_contains_name_in_list(username, domain, diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 045de6f2d3..c238f40cfd 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -88,7 +88,8 @@ static bool check_user_ok(connection_struct *conn, uint16_t vuid, readonly_share = is_share_read_only_for_token( server_info->unix_name, pdb_get_domain(server_info->sam_account), - server_info->ptok, snum); + server_info->ptok, + conn); if (!readonly_share && !share_access_check(server_info->ptok, lp_servicename(snum), -- cgit From 6ce29dc9add1252b0ded9d2c1c2b6bae74604cc4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 18 Nov 2008 17:03:38 +0100 Subject: Fix trans2findfirst for the large directory optimization With case sensitive = yes preserve case = no short preserve case = no default case = upper a "dir FOO.txt" would not find "FOO.TXT" because FOO.txt ends up unconverted in the mask for mask_match. Jeremy, please check! Volker --- source3/smbd/filename.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 562f1e8d94..3eb2d63734 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -206,6 +206,11 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, *pp_saved_last_component = talloc_strdup(ctx, orig_path); } + if (conn->case_sensitive && !conn->case_preserve && + !conn->short_case_preserve) { + strnorm(*pp_saved_last_component, + lp_defaultcase(SNUM(conn))); + } } if (!(name = talloc_strdup(ctx, orig_path))) { -- cgit From 93fd28a350c1f2652a24daead8ca6e4c8ff696cb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Nov 2008 10:57:54 -0800 Subject: Re-structure Volker's patch to "Fix trans2findfirst for the large directory optimization". Makes the change clearer. Jeremy. --- source3/smbd/filename.c | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 3eb2d63734..392264bfc0 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -194,30 +194,39 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, return result; } + if (!(name = talloc_strdup(ctx, orig_path))) { + DEBUG(0, ("talloc_strdup failed\n")); + return NT_STATUS_NO_MEMORY; + } + + /* + * Large directory fix normalization. If we're case sensitive, and + * the case preserving parameters are set to "no", normalize the case of + * the incoming filename from the client WHETHER IT EXISTS OR NOT ! + * This is in conflict with the current (3.0.20) man page, but is + * what people expect from the "large directory howto". I'll update + * the man page. Thanks to jht@samba.org for finding this. JRA. + */ + + if (conn->case_sensitive && !conn->case_preserve && + !conn->short_case_preserve) { + strnorm(name, lp_defaultcase(SNUM(conn))); + } + /* * Ensure saved_last_component is valid even if file exists. */ if(pp_saved_last_component) { - end = strrchr_m(orig_path, '/'); + end = strrchr_m(name, '/'); if (end) { *pp_saved_last_component = talloc_strdup(ctx, end + 1); } else { *pp_saved_last_component = talloc_strdup(ctx, - orig_path); - } - if (conn->case_sensitive && !conn->case_preserve && - !conn->short_case_preserve) { - strnorm(*pp_saved_last_component, - lp_defaultcase(SNUM(conn))); + name); } } - if (!(name = talloc_strdup(ctx, orig_path))) { - DEBUG(0, ("talloc_strdup failed\n")); - return NT_STATUS_NO_MEMORY; - } - if (!lp_posix_pathnames()) { stream = strchr_m(name, ':'); @@ -232,20 +241,6 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, } } - /* - * Large directory fix normalization. If we're case sensitive, and - * the case preserving parameters are set to "no", normalize the case of - * the incoming filename from the client WHETHER IT EXISTS OR NOT ! - * This is in conflict with the current (3.0.20) man page, but is - * what people expect from the "large directory howto". I'll update - * the man page. Thanks to jht@samba.org for finding this. JRA. - */ - - if (conn->case_sensitive && !conn->case_preserve && - !conn->short_case_preserve) { - strnorm(name, lp_defaultcase(SNUM(conn))); - } - start = name; /* If we're providing case insentive semantics or -- cgit From 0e62bb39de93433dfeb7f822ec1026da7ed643f4 Mon Sep 17 00:00:00 2001 From: Dina Fine Date: Tue, 18 Nov 2008 12:45:42 -0800 Subject: Fix bug #5908 - Samba 3.0.32 - internal change notify on share directory fails" --- source3/smbd/notify.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 5a517654bf..2d0811bc1c 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -339,6 +339,9 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter, { char *fullpath; + if (path[0] == '.' && path[1] == '/') { + path += 2; + } if (asprintf(&fullpath, "%s/%s", conn->connectpath, path) == -1) { DEBUG(0, ("asprintf failed\n")); return; -- cgit From 293372ff8d32a48d764171ecca3a8c55dfe0e818 Mon Sep 17 00:00:00 2001 From: Yasuma Takeda Date: Thu, 20 Nov 2008 11:38:37 -0800 Subject: Fix bug #5909 - MS-DFS does not work on Vista, if link name includes multibyte character. --- source3/smbd/msdfs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 32240ff0d5..1504b19169 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -923,7 +923,6 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, static int setup_ver2_dfs_referral(const char *pathname, char **ppdata, struct junction_map *junction, - int consumedcnt, bool self_referral) { char* pdata = *ppdata; @@ -988,7 +987,8 @@ static int setup_ver2_dfs_referral(const char *pathname, memcpy(pdata+uni_reqpathoffset2,uni_requestedpath,requestedpathlen); /* create the header */ - SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ + SSVAL(pdata,0,requestedpathlen - 2); /* UCS2 of path consumed minus + 2 byte null */ /* number of referral in this pkt */ SSVAL(pdata,2,junction->referral_count); if(self_referral) { @@ -1037,7 +1037,6 @@ static int setup_ver2_dfs_referral(const char *pathname, static int setup_ver3_dfs_referral(const char *pathname, char **ppdata, struct junction_map *junction, - int consumedcnt, bool self_referral) { char *pdata = *ppdata; @@ -1084,7 +1083,8 @@ static int setup_ver3_dfs_referral(const char *pathname, *ppdata = pdata; /* create the header */ - SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ + SSVAL(pdata,0,reqpathlen - 2); /* UCS2 of path consumed minus + 2 byte null */ SSVAL(pdata,2,junction->referral_count); /* number of referral */ if(self_referral) { SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); @@ -1224,11 +1224,11 @@ int setup_dfs_referral(connection_struct *orig_conn, case 2: reply_size = setup_ver2_dfs_referral(pathnamep, ppdata, junction, - consumedcnt, self_referral); + self_referral); break; case 3: reply_size = setup_ver3_dfs_referral(pathnamep, ppdata, - junction, consumedcnt, self_referral); + junction, self_referral); break; default: DEBUG(0,("setup_dfs_referral: Invalid dfs referral " -- cgit From 97fb05c2c0d0b08f3ed5aa7358a4d6d8c1725012 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Nov 2008 12:14:53 -0800 Subject: First part of fix for bug #5903 - vfs_streams_xattr breaks contents of the file. Restructures parts of open code so that fsp must be allocated before calling open_file_ntcreate(_internal). Also fix up file ref-counting inside files.c. Jeremy. --- source3/smbd/close.c | 8 +-- source3/smbd/fake_file.c | 1 - source3/smbd/files.c | 74 +++++++++++------------- source3/smbd/open.c | 143 +++++++++++++++++++++++++++-------------------- source3/smbd/reply.c | 9 ++- 5 files changed, 126 insertions(+), 109 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index d4c531ab19..ce918ab6a3 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -106,8 +106,7 @@ static void check_magic(struct files_struct *fsp) static NTSTATUS close_filestruct(files_struct *fsp) { NTSTATUS status = NT_STATUS_OK; - connection_struct *conn = fsp->conn; - + if (fsp->fh->fd != -1) { if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) { status = map_nt_error_from_unix(errno); @@ -115,9 +114,8 @@ static NTSTATUS close_filestruct(files_struct *fsp) delete_write_cache(fsp); } - conn->num_files_open--; return status; -} +} /**************************************************************************** If any deferred opens are waiting on this close, notify them. @@ -583,7 +581,7 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp, DEBUG(2,("%s closed file %s (numopen=%d) %s\n", conn->server_info->unix_name,fsp->fsp_name, - conn->num_files_open, + conn->num_files_open - 1, nt_errstr(status) )); file_free(req, fsp); diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 58b09604c4..7feedcc9f9 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -141,7 +141,6 @@ NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn, return NT_STATUS_NO_MEMORY; } - conn->num_files_open++; *result = fsp; return NT_STATUS_OK; } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index d3bfce7499..1a3a997e59 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -129,6 +129,8 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn, ZERO_STRUCT(fsp_fi_cache); + conn->num_files_open++; + *result = fsp; return NT_STATUS_OK; } @@ -420,9 +422,7 @@ void file_free(struct smb_request *req, files_struct *fsp) DEBUG(5,("freed files structure %d (%d used)\n", fsp->fnum, files_used)); - /* this is paranoia, just in case someone tries to reuse the - information */ - ZERO_STRUCTP(fsp); + fsp->conn->num_files_open--; if ((req != NULL) && (fsp == req->chain_fsp)) { req->chain_fsp = NULL; @@ -438,6 +438,10 @@ void file_free(struct smb_request *req, files_struct *fsp) vfs_remove_fsp_extension(fsp->vfs_extension->owner, fsp); } + /* this is paranoia, just in case someone tries to reuse the + information */ + ZERO_STRUCTP(fsp); + SAFE_FREE(fsp); } @@ -484,46 +488,34 @@ files_struct *file_fsp(struct smb_request *req, uint16 fid) Duplicate the file handle part for a DOS or FCB open. ****************************************************************************/ -NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *fsp, +void dup_file_fsp(struct smb_request *req, files_struct *from, uint32 access_mask, uint32 share_access, - uint32 create_options, files_struct **result) + uint32 create_options, files_struct *to) { - NTSTATUS status; - files_struct *dup_fsp; - - status = file_new(NULL, fsp->conn, &dup_fsp); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - SAFE_FREE(dup_fsp->fh); - - dup_fsp->fh = fsp->fh; - dup_fsp->fh->ref_count++; - - dup_fsp->file_id = fsp->file_id; - dup_fsp->initial_allocation_size = fsp->initial_allocation_size; - dup_fsp->mode = fsp->mode; - dup_fsp->file_pid = fsp->file_pid; - dup_fsp->vuid = fsp->vuid; - dup_fsp->open_time = fsp->open_time; - dup_fsp->access_mask = access_mask; - dup_fsp->share_access = share_access; - dup_fsp->oplock_type = fsp->oplock_type; - dup_fsp->can_lock = fsp->can_lock; - dup_fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False; - if (!CAN_WRITE(fsp->conn)) { - dup_fsp->can_write = False; + SAFE_FREE(to->fh); + + to->fh = from->fh; + to->fh->ref_count++; + + to->file_id = from->file_id; + to->initial_allocation_size = from->initial_allocation_size; + to->mode = from->mode; + to->file_pid = from->file_pid; + to->vuid = from->vuid; + to->open_time = from->open_time; + to->access_mask = access_mask; + to->share_access = share_access; + to->oplock_type = from->oplock_type; + to->can_lock = from->can_lock; + to->can_read = (access_mask & (FILE_READ_DATA)) ? True : False; + if (!CAN_WRITE(from->conn)) { + to->can_write = False; } else { - dup_fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False; + to->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False; } - dup_fsp->print_file = fsp->print_file; - dup_fsp->modified = fsp->modified; - dup_fsp->is_directory = fsp->is_directory; - dup_fsp->aio_write_behind = fsp->aio_write_behind; - string_set(&dup_fsp->fsp_name,fsp->fsp_name); - - *result = dup_fsp; - return NT_STATUS_OK; + to->print_file = from->print_file; + to->modified = from->modified; + to->is_directory = from->is_directory; + to->aio_write_behind = from->aio_write_behind; + string_set(&to->fsp_name,from->fsp_name); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3fd0d1a03a..aca64917b5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -462,7 +462,7 @@ static NTSTATUS open_file(files_struct *fsp, conn->server_info->unix_name, fsp->fsp_name, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), - conn->num_files_open + 1)); + conn->num_files_open)); errno = 0; return NT_STATUS_OK; @@ -951,9 +951,10 @@ static bool open_match_attributes(connection_struct *conn, Try and find a duplicated file handle. ****************************************************************************/ -static files_struct *fcb_or_dos_open(struct smb_request *req, +static NTSTATUS fcb_or_dos_open(struct smb_request *req, connection_struct *conn, - const char *fname, + files_struct *fsp_to_dup_into, + const char *fname, struct file_id id, uint16 file_pid, uint16 vuid, @@ -962,7 +963,6 @@ static files_struct *fcb_or_dos_open(struct smb_request *req, uint32 create_options) { files_struct *fsp; - files_struct *dup_fsp; DEBUG(5,("fcb_or_dos_open: attempting old open semantics for " "file %s.\n", fname )); @@ -991,23 +991,21 @@ static files_struct *fcb_or_dos_open(struct smb_request *req, } if (!fsp) { - return NULL; + return NT_STATUS_NOT_FOUND; } /* quite an insane set of semantics ... */ if (is_executable(fname) && (fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) { DEBUG(10,("fcb_or_dos_open: file fail due to is_executable.\n")); - return NULL; + return NT_STATUS_INVALID_PARAMETER; } /* We need to duplicate this fsp. */ - if (!NT_STATUS_IS_OK(dup_file_fsp(req, fsp, access_mask, share_access, - create_options, &dup_fsp))) { - return NULL; - } + dup_file_fsp(req, fsp, access_mask, share_access, + create_options, fsp_to_dup_into); - return dup_fsp; + return NT_STATUS_OK; } /**************************************************************************** @@ -1249,10 +1247,10 @@ static NTSTATUS calculate_access_mask(connection_struct *conn, } /**************************************************************************** - Open a file with a share mode. + Open a file with a share mode. Passed in an already created files_struct *. ****************************************************************************/ -NTSTATUS open_file_ntcreate(connection_struct *conn, +static NTSTATUS open_file_ntcreate_internal(connection_struct *conn, struct smb_request *req, const char *fname, SMB_STRUCT_STAT *psbuf, @@ -1264,7 +1262,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, int oplock_request, /* internal Samba oplock codes. */ /* Information (FILE_EXISTS etc.) */ int *pinfo, - files_struct **result) + files_struct *fsp) { int flags=0; int flags2=0; @@ -1274,7 +1272,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, bool new_file_created = False; struct file_id id; NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; - files_struct *fsp = NULL; mode_t new_unx_mode = (mode_t)0; mode_t unx_mode = (mode_t)0; int info; @@ -1291,7 +1288,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, ZERO_STRUCT(id); if (conn->printer) { - /* + /* * Printers are handled completely differently. * Most of the passed parameters are ignored. */ @@ -1302,7 +1299,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname)); - return print_fsp_open(req, conn, fname, req->vuid, result); + return print_fsp_open(req, conn, fname, req->vuid, fsp); } if (!parent_dirname_talloc(talloc_tos(), fname, &parent_dir, @@ -1366,7 +1363,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { return status; - } + } if (!posix_open) { new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; @@ -1533,7 +1530,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, flags2 |= O_SYNC; } #endif /* O_SYNC */ - + if (posix_open && (access_mask & FILE_APPEND_DATA)) { flags2 |= O_APPEND; } @@ -1560,11 +1557,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_ACCESS_DENIED; } - status = file_new(req, conn, &fsp); - if(!NT_STATUS_IS_OK(status)) { - return status; - } - fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->share_access = share_access; fsp->fh->private_options = create_options; @@ -1589,7 +1581,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, fname, &old_write_time); if (lck == NULL) { - file_free(req, fsp); DEBUG(0, ("Could not get share mode lock\n")); return NT_STATUS_SHARING_VIOLATION; } @@ -1600,7 +1591,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, oplock_request)) { schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); - file_free(req, fsp); return NT_STATUS_SHARING_VIOLATION; } @@ -1620,7 +1610,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, oplock_request)) { schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); - file_free(req, fsp); return NT_STATUS_SHARING_VIOLATION; } } @@ -1628,7 +1617,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { /* DELETE_PENDING is not deferred for a second */ TALLOC_FREE(lck); - file_free(req, fsp); return status; } @@ -1643,33 +1631,31 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (create_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { - files_struct *fsp_dup; - if (req == NULL) { DEBUG(0, ("DOS open without an SMB " "request!\n")); TALLOC_FREE(lck); - file_free(req, fsp); return NT_STATUS_INTERNAL_ERROR; } /* Use the client requested access mask here, * not the one we open with. */ - fsp_dup = fcb_or_dos_open(req, conn, fname, id, - req->smbpid, - req->vuid, - access_mask, - share_access, - create_options); - - if (fsp_dup) { + status = fcb_or_dos_open(req, + conn, + fsp, + fname, + id, + req->smbpid, + req->vuid, + access_mask, + share_access, + create_options); + + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(lck); - file_free(req, fsp); if (pinfo) { *pinfo = FILE_WAS_OPENED; } - conn->num_files_open++; - *result = fsp_dup; return NT_STATUS_OK; } } @@ -1697,7 +1683,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, can_access = False; } - /* + /* * If we're returning a share violation, ensure we * cope with the braindead 1 second delay. */ @@ -1750,7 +1736,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } else { status = NT_STATUS_ACCESS_DENIED; } - file_free(req, fsp); return status; } @@ -1788,7 +1773,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (lck != NULL) { TALLOC_FREE(lck); } - file_free(req, fsp); return fsp_open; } @@ -1819,7 +1803,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, DEBUG(0, ("open_file_ntcreate: Could not get share " "mode lock for %s\n", fname)); fd_close(fsp); - file_free(req, fsp); return NT_STATUS_SHARING_VIOLATION; } @@ -1830,7 +1813,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); fd_close(fsp); - file_free(req, fsp); return NT_STATUS_SHARING_VIOLATION; } @@ -1849,7 +1831,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); fd_close(fsp); - file_free(req, fsp); return NT_STATUS_SHARING_VIOLATION; } } @@ -1858,7 +1839,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, struct deferred_open_record state; fd_close(fsp); - file_free(req, fsp); state.delayed_for_oplocks = False; state.id = id; @@ -1900,7 +1880,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, TALLOC_FREE(lck); fd_close(fsp); - file_free(req, fsp); return NT_STATUS_SHARING_VIOLATION; } @@ -1926,7 +1905,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, status = map_nt_error_from_unix(errno); TALLOC_FREE(lck); fd_close(fsp); - file_free(req, fsp); return status; } } @@ -1958,7 +1936,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, *pinfo = info; } - /* + /* * Setup the oplock info in both the shared memory and * file structs. */ @@ -1990,14 +1968,13 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, del_share_mode(lck, fsp); TALLOC_FREE(lck); fd_close(fsp); - file_free(req, fsp); return status; } /* Note that here we set the *inital* delete on close flag, not the regular one. The magic gets handled in close. */ fsp->initial_delete_on_close = True; } - + if (new_file_created) { /* Files should be initially set as archive */ if (lp_map_archive(SNUM(conn)) || @@ -2066,10 +2043,57 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } TALLOC_FREE(lck); - conn->num_files_open++; + return NT_STATUS_OK; +} + +/**************************************************************************** + Open a file with a share mode. +****************************************************************************/ + +NTSTATUS open_file_ntcreate(connection_struct *conn, + struct smb_request *req, + const char *fname, + SMB_STRUCT_STAT *psbuf, + uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */ + uint32 share_access, /* share constants (FILE_SHARE_READ etc) */ + uint32 create_disposition, /* FILE_OPEN_IF etc. */ + uint32 create_options, /* options such as delete on close. */ + uint32 new_dos_attributes, /* attributes used for new file. */ + int oplock_request, /* internal Samba oplock codes. */ + /* Information (FILE_EXISTS etc.) */ + int *pinfo, + files_struct **result) +{ + NTSTATUS status; + files_struct *fsp = NULL; + + *result = NULL; + + status = file_new(req, conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; + } + + status = open_file_ntcreate_internal(conn, + req, + fname, + psbuf, + access_mask, + share_access, + create_disposition, + create_options, + new_dos_attributes, + oplock_request, + pinfo, + fsp); + + if(!NT_STATUS_IS_OK(status)) { + file_free(req, fsp); + return status; + } *result = fsp; - return NT_STATUS_OK; + return status; } /**************************************************************************** @@ -2097,10 +2121,9 @@ NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn, status = open_file(fsp, conn, NULL, NULL, NULL, fname, psbuf, O_WRONLY, 0, FILE_WRITE_DATA, FILE_WRITE_DATA); - /* + /* * This is not a user visible file open. - * Don't set a share mode and don't increment - * the conn->num_files_open. + * Don't set a share mode. */ if (!NT_STATUS_IS_OK(status)) { @@ -2431,8 +2454,6 @@ NTSTATUS open_directory(connection_struct *conn, *pinfo = info; } - conn->num_files_open++; - *result = fsp; return NT_STATUS_OK; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c363ed5609..1f99db2de4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4558,8 +4558,15 @@ void reply_printopen(struct smb_request *req) return; } + status = file_new(req, conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + END_PROFILE(SMBsplopen); + return; + } + /* Open for exclusive use, write only. */ - status = print_fsp_open(req, conn, NULL, req->vuid, &fsp); + status = print_fsp_open(req, conn, NULL, req->vuid, fsp); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); -- cgit From 8d674e351ada654ab79d635851ac73cef71d4753 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Nov 2008 15:42:03 -0800 Subject: Second part of the fix for bug #5903 - vfs_streams_xattr breaks contents of the file (also fix a bad merge of the previous patch from 3.3). Jeremy. --- source3/smbd/open.c | 61 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aca64917b5..a6867e077c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1651,7 +1651,7 @@ static NTSTATUS open_file_ntcreate_internal(connection_struct *conn, share_access, create_options); - if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_IS_OK(status)) { TALLOC_FREE(lck); if (pinfo) { *pinfo = FILE_WAS_OPENED; @@ -2878,10 +2878,42 @@ NTSTATUS create_file_unixpath(connection_struct *conn, * Ordinary file case. */ - status = open_file_ntcreate( - conn, req, fname, &sbuf, access_mask, share_access, - create_disposition, create_options, file_attributes, - oplock_request, &info, &fsp); + if (base_fsp) { + /* + * We're opening the stream element of a base_fsp + * we already opened. We need to initialize + * the fsp first, and set up the base_fsp pointer. + */ + status = file_new(req, conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + goto fail; + } + + fsp->base_fsp = base_fsp; + + status = open_file_ntcreate_internal(conn, + req, + fname, + &sbuf, + access_mask, + share_access, + create_disposition, + create_options, + file_attributes, + oplock_request, + &info, + fsp); + + if(!NT_STATUS_IS_OK(status)) { + file_free(req, fsp); + fsp = NULL; + } + } else { + status = open_file_ntcreate( + conn, req, fname, &sbuf, access_mask, share_access, + create_disposition, create_options, file_attributes, + oplock_request, &info, &fsp); + } if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { @@ -2908,6 +2940,8 @@ NTSTATUS create_file_unixpath(connection_struct *conn, goto fail; } + fsp->base_fsp = base_fsp; + /* * According to the MS documentation, the only time the security * descriptor is applied to the opened file is iff we *created* the @@ -2994,16 +3028,6 @@ NTSTATUS create_file_unixpath(connection_struct *conn, DEBUG(10, ("create_file_unixpath: info=%d\n", info)); - /* - * Set fsp->base_fsp late enough that we can't "goto fail" anymore. In - * the fail: branch we call close_file(fsp, ERROR_CLOSE) which would - * also close fsp->base_fsp which we have to also do explicitly in - * this routine here, as not in all "goto fail:" we have the fsp set - * up already to be initialized with the base_fsp. - */ - - fsp->base_fsp = base_fsp; - *result = fsp; if (pinfo != NULL) { *pinfo = info; @@ -3022,6 +3046,13 @@ NTSTATUS create_file_unixpath(connection_struct *conn, DEBUG(10, ("create_file_unixpath: %s\n", nt_errstr(status))); if (fsp != NULL) { + if (base_fsp && fsp->base_fsp == base_fsp) { + /* + * The close_file below will close + * fsp->base_fsp. + */ + base_fsp = NULL; + } close_file(req, fsp, ERROR_CLOSE); fsp = NULL; } -- cgit From 83ff6979f504d50caf725ee62549604630b69be7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Nov 2008 18:20:38 -0800 Subject: Fix the logic bug that caused us to run into kernel oplocks on an open for a stream inside a file with stream_xattr module. On opening the base_fsp we must break existing oplocks. Jeremy. --- source3/smbd/open.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a6867e077c..018d104d0b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2830,7 +2830,13 @@ NTSTATUS create_file_unixpath(connection_struct *conn, break; } - status = create_file_unixpath(conn, NULL, base, 0, + DEBUG(10, ("Recursing into create_file_unixpath for " + "base %s\n", base)); + + /* This call will break any oplock on the base file, + * but will not actually open an underlying fd. */ + + status = create_file_unixpath(conn, req, base, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, -- cgit From 338303eb379320411829ee3dd1621e490f8d7fe1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Nov 2008 22:48:37 -0800 Subject: Rever 83ff6979f504d50caf725ee62549604630b69be7 - "Fix the logic bug that caused us to run into kernel oplocks on an open for a stream inside a file with stream_xattr module. On opening the base_fsp we must break existing oplocks." as it broke make test. Jeremy. --- source3/smbd/open.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 018d104d0b..a6867e077c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2830,13 +2830,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, break; } - DEBUG(10, ("Recursing into create_file_unixpath for " - "base %s\n", base)); - - /* This call will break any oplock on the base file, - * but will not actually open an underlying fd. */ - - status = create_file_unixpath(conn, req, base, 0, + status = create_file_unixpath(conn, NULL, base, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, -- cgit From ed27d91068ca45a2f2924cb2d53c3fdf856c5c47 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 23 Nov 2008 22:21:26 +0100 Subject: Add auth_serversupplied_info to create_conn_struct srvsvc needs it, as will printing --- source3/smbd/msdfs.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 1504b19169..d46be64262 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -219,6 +219,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, connection_struct **pconn, int snum, const char *path, + struct auth_serversupplied_info *server_info, char **poldcwd) { connection_struct *conn; @@ -254,6 +255,15 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, conn->params->service = snum; + if (server_info != NULL) { + conn->server_info = copy_serverinfo(conn, server_info); + if (conn->server_info == NULL) { + DEBUG(0, ("copy_serverinfo failed\n")); + TALLOC_FREE(conn); + return NT_STATUS_NO_MEMORY; + } + } + set_conn_connectpath(conn, connpath); if (!smbd_vfs_init(conn)) { @@ -881,7 +891,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, } status = create_conn_struct(ctx, &conn, snum, lp_pathname(snum), - &oldpath); + NULL, &oldpath); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(pdp); return status; @@ -1321,7 +1331,7 @@ static bool junction_to_local_path(const struct junction_map *jucn, return False; } status = create_conn_struct(talloc_tos(), conn_out, snum, - lp_pathname(snum), oldpath); + lp_pathname(snum), NULL, oldpath); if (!NT_STATUS_IS_OK(status)) { return False; } @@ -1455,7 +1465,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) */ status = create_conn_struct(talloc_tos(), &conn, snum, connect_path, - &cwd); + NULL, &cwd); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("create_conn_struct failed: %s\n", nt_errstr(status))); @@ -1523,7 +1533,8 @@ static int form_junctions(TALLOC_CTX *ctx, * Fake up a connection struct for the VFS layer. */ - status = create_conn_struct(ctx, &conn, snum, connect_path, &cwd); + status = create_conn_struct(ctx, &conn, snum, connect_path, NULL, + &cwd); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("create_conn_struct failed: %s\n", nt_errstr(status))); -- cgit From 798b9e1ad6bbdcf873285d0e1c5008e566744162 Mon Sep 17 00:00:00 2001 From: Steven Danneman Date: Sun, 23 Nov 2008 18:20:19 -0800 Subject: Fix to allow setting of NULL DACL/SACL This is a modification of Jeremy's 7522ef15aca2429ef57c75d8297dd8121e79c9da commit. If no DACL/SACL is present in the packet, the SEC_INFO field should still be passed down as is to the VFS layer to signal the creation of a NULL DACL/SACL. As seen in metze RAW-ACL test_nttrans_create_null_dacl(), a NULL DACL is set regardless of the SEC_DESC_DACL_PRESENT bit being set. --- source3/smbd/nttrans.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 52c16e2ac6..8a18c87903 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -721,21 +721,12 @@ static NTSTATUS set_sd(files_struct *fsp, uint8 *data, uint32 sd_len, return status; } - if (psd->owner_sid==0) { + if (psd->owner_sid == NULL) { security_info_sent &= ~OWNER_SECURITY_INFORMATION; } - if (psd->group_sid==0) { + if (psd->group_sid == NULL) { security_info_sent &= ~GROUP_SECURITY_INFORMATION; } - if (psd->sacl==0) { - security_info_sent &= ~SACL_SECURITY_INFORMATION; - } - if (security_info_sent & DACL_SECURITY_INFORMATION) { - psd->type |= SEC_DESC_DACL_PRESENT; - } - if (psd->dacl==0) { - security_info_sent &= ~DACL_SECURITY_INFORMATION; - } /* Convert all the generic bits. */ security_acl_map_generic(psd->dacl, &file_generic_mapping); -- cgit From 6f840dd678f8f19b84c042816e75e85d1077904e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 23 Nov 2008 23:14:39 +0100 Subject: Remove unused make_connection_with_chdir() --- source3/smbd/service.c | 32 -------------------------------- 1 file changed, 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 05197021a3..0dea615fb5 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1123,38 +1123,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } -/*************************************************************************************** - Simple wrapper function for make_connection() to include a call to - vfs_chdir() - **************************************************************************************/ - -connection_struct *make_connection_with_chdir(const char *service_in, - DATA_BLOB password, - const char *dev, uint16 vuid, - NTSTATUS *status) -{ - connection_struct *conn = NULL; - - conn = make_connection(service_in, password, dev, vuid, status); - - /* - * make_connection() does not change the directory for us any more - * so we have to do it as a separate step --jerry - */ - - if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) { - DEBUG(0,("make_connection_with_chdir: Can't change " - "directory to %s for [print$] (%s)\n", - conn->connectpath,strerror(errno))); - yield_connection(conn, lp_servicename(SNUM(conn))); - conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; - return NULL; - } - - return conn; -} - /**************************************************************************** Make a connection to a service. * -- cgit From 907f126d3e84b7acddf70f8da12010d6b22d8e99 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 23 Nov 2008 23:48:17 +0100 Subject: Get rid of pipes_struct->pipe_user, we have server_info now --- YESSS! --- source3/smbd/uid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index c238f40cfd..ca7df264e2 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -318,9 +318,9 @@ bool become_authenticated_pipe_user(pipes_struct *p) if (!push_sec_ctx()) return False; - set_sec_ctx(p->pipe_user.ut.uid, p->pipe_user.ut.gid, - p->pipe_user.ut.ngroups, p->pipe_user.ut.groups, - p->pipe_user.nt_user_token); + set_sec_ctx(p->server_info->utok.uid, p->server_info->utok.gid, + p->server_info->utok.ngroups, p->server_info->utok.groups, + p->server_info->ptok); return True; } -- cgit From 2c458935933daf219be276b06c6eb1b5752f2638 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 24 Nov 2008 15:28:11 -0800 Subject: Fix bug #5873 - ACL inheritance cannot be broken. This regresses #4308, but that will have to be fixed another way. Jeremy. --- source3/smbd/posix_acls.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 7ca2ed787b..0529d2765e 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3211,6 +3211,9 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) return ret; } +#if 0 +/* Disable this - prevents ACL inheritance from the ACL editor. JRA. */ + /**************************************************************************** Take care of parent ACL inheritance. ****************************************************************************/ @@ -3398,6 +3401,7 @@ NTSTATUS append_parent_acl(files_struct *fsp, *pp_new_sd = psd; return status; } +#endif /**************************************************************************** Reply to set a security descriptor on an fsp. security_info_sent is the @@ -3510,6 +3514,9 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); +#if 0 + /* Disable this - prevents ACL inheritance from the ACL editor. JRA. */ + /* See here: http://www.codeproject.com/KB/winsdk/accessctrl2.aspx * for details and also the log trace in bug #4308. JRA. */ @@ -3527,6 +3534,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC } psd = new_sd; } +#endif acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid, &file_ace_list, &dir_ace_list, security_info_sent, psd); -- cgit From 114f519233cd37bfd623db820e888469c75fab26 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 8 Nov 2008 17:14:06 +0100 Subject: Fix the offset checks in the trans routines This fixes a potential crash bug, a client can make us read memory we should not read. Luckily I got the disp checks right... Volker (cherry picked from commit 64a1d80851da5b05e70ec6c96f6e9bd473748369) (cherry picked from commit f04c5650a3aeca23591ddc781c4b297caaf9bb3f) --- source3/smbd/ipc.c | 6 +++--- source3/smbd/nttrans.c | 6 +++--- source3/smbd/trans2.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 26a4212ec9..a617756a53 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -769,10 +769,10 @@ void reply_transs(struct smb_request *req) goto bad_param; } - if (ddisp > av_size || + if (doff > av_size || dcnt > av_size || - ddisp+dcnt > av_size || - ddisp+dcnt < ddisp) { + doff+dcnt > av_size || + doff+dcnt < doff) { goto bad_param; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8a18c87903..329ba23ddd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2818,10 +2818,10 @@ void reply_nttranss(struct smb_request *req) goto bad_param; } - if (ddisp > av_size || + if (doff > av_size || dcnt > av_size || - ddisp+dcnt > av_size || - ddisp+dcnt < ddisp) { + doff+dcnt > av_size || + doff+dcnt < doff) { goto bad_param; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c385c6ccb1..0c63588ccc 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7811,10 +7811,10 @@ void reply_transs2(struct smb_request *req) goto bad_param; } - if (ddisp > av_size || + if (doff > av_size || dcnt > av_size || - ddisp+dcnt > av_size || - ddisp+dcnt < ddisp) { + doff+dcnt > av_size || + doff+dcnt < doff) { goto bad_param; } -- cgit From 599707c87a739811ba426e44b11189e1ddba078e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 8 Nov 2008 15:44:20 +0100 Subject: Remove two direct inbuf references from reply_sesssetup_and_X_spnego() --- source3/smbd/sesssetup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index fde6cdc160..24a201013a 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1171,7 +1171,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) const char *p2; uint16 data_blob_len = SVAL(req->vwv+7, 0); enum remote_arch_types ra_type = get_remote_arch(); - int vuid = SVAL(req->inbuf,smb_uid); + int vuid = req->vuid; user_struct *vuser = NULL; NTSTATUS status = NT_STATUS_OK; uint16 smbpid = req->smbpid; @@ -1203,7 +1203,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) file_save("negotiate.dat", blob1.data, blob1.length); #endif - p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len; + p2 = (char *)req->buf + data_blob_len; p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2, STR_TERMINATE); -- cgit From 4a322398c5ffaf238eba1e7bfbe47e2d093c7c4d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 8 Nov 2008 16:03:07 +0100 Subject: Remove an unused variable --- source3/smbd/trans2.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0c63588ccc..3a28bd424f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7533,7 +7533,6 @@ void reply_trans2(struct smb_request *req) unsigned int psoff; unsigned int pscnt; unsigned int tran_call; - unsigned int size; unsigned int av_size; struct trans_state *state; NTSTATUS result; @@ -7551,7 +7550,6 @@ void reply_trans2(struct smb_request *req) psoff = SVAL(req->vwv+10, 0); pscnt = SVAL(req->vwv+9, 0); tran_call = SVAL(req->vwv+14, 0); - size = smb_len(req->inbuf) + 4; av_size = smb_len(req->inbuf); result = allow_new_trans(conn->pending_trans, req->mid); -- cgit From 9da3101e449649f0614240f13157ac81e17b2e90 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 8 Nov 2008 16:14:12 +0100 Subject: Remove the variable "size" from reply_trans This converts the range checks for the setup[] array to rely on req->wct being set correctly in init_smb_request. As that already verifies the vwv array to be in the range of the smb_request inbuf, we don't have to do overflow checks here anymore. Jeremy, please check thoroughly! :-) Thanks, Volker --- source3/smbd/ipc.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index a617756a53..bf9b1d87c5 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -503,7 +503,6 @@ void reply_trans(struct smb_request *req) unsigned int pscnt; struct trans_state *state; NTSTATUS result; - unsigned int size; unsigned int av_size; START_PROFILE(SMBtrans); @@ -514,7 +513,6 @@ void reply_trans(struct smb_request *req) return; } - size = smb_len(req->inbuf) + 4; av_size = smb_len(req->inbuf); dsoff = SVAL(req->vwv+12, 0); dscnt = SVAL(req->vwv+11, 0); @@ -624,6 +622,19 @@ void reply_trans(struct smb_request *req) if (state->setup_count) { unsigned int i; + + /* + * No overflow possible here, state->setup_count is an + * unsigned int, being filled by a single byte from + * CVAL(req->vwv+13, 0) above. The cast in the comparison + * below is not necessary, it's here to clarify things. The + * validity of req->vwv and req->wct has been checked in + * init_smb_request already. + */ + if (state->setup_count + 14 > (unsigned int)req->wct) { + goto bad_param; + } + if((state->setup = TALLOC_ARRAY( state, uint16, state->setup_count)) == NULL) { DEBUG(0,("reply_trans: setup malloc fail for %u " @@ -636,17 +647,10 @@ void reply_trans(struct smb_request *req) END_PROFILE(SMBtrans); return; } - if (req->inbuf+smb_vwv14+(state->setup_count*SIZEOFWORD) > - req->inbuf + size) - goto bad_param; - if ((smb_vwv14+(state->setup_count*SIZEOFWORD) < smb_vwv14) || - (smb_vwv14+(state->setup_count*SIZEOFWORD) < - (state->setup_count*SIZEOFWORD))) - goto bad_param; - for (i=0;isetup_count;i++) - state->setup[i] = SVAL(req->inbuf, - smb_vwv14+i*SIZEOFWORD); + for (i=0;isetup_count;i++) { + state->setup[i] = SVAL(req->vwv + 14 + i, 0); + } } state->received_param = pscnt; -- cgit From 738271fc2026b2911b7d20a73496989641714df3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 8 Nov 2008 16:14:12 +0100 Subject: Remove the variable "size" from reply_nttrans This converts the range checks for the setup[] array to rely on req->wct being set correctly in init_smb_request. As that already verifies the vwv array to be in the range of the smb_request inbuf, we don't have to do overflow checks here anymore. Jeremy, please check thoroughly! :-) Thanks, Volker --- source3/smbd/nttrans.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 329ba23ddd..b516f02c21 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2529,7 +2529,6 @@ void reply_nttrans(struct smb_request *req) uint16 function_code; NTSTATUS result; struct trans_state *state; - uint32_t size; uint32_t av_size; START_PROFILE(SMBnttrans); @@ -2540,7 +2539,6 @@ void reply_nttrans(struct smb_request *req) return; } - size = smb_len(req->inbuf) + 4; av_size = smb_len(req->inbuf); pscnt = IVAL(req->vwv+9, 1); psoff = IVAL(req->vwv+11, 1); @@ -2676,6 +2674,19 @@ void reply_nttrans(struct smb_request *req) if(state->setup_count > 0) { DEBUG(10,("reply_nttrans: state->setup_count = %d\n", state->setup_count)); + + /* + * No overflow possible here, state->setup_count is an + * unsigned int, being filled by a single byte from + * CVAL(req->vwv+13, 0) above. The cast in the comparison + * below is not necessary, it's here to clarify things. The + * validity of req->vwv and req->wct has been checked in + * init_smb_request already. + */ + if ((state->setup_count/2) + 19 > (unsigned int)req->wct) { + goto bad_param; + } + state->setup = (uint16 *)TALLOC(state, state->setup_count); if (state->setup == NULL) { DEBUG(0,("reply_nttrans : Out of memory\n")); @@ -2687,14 +2698,6 @@ void reply_nttrans(struct smb_request *req) return; } - if ((smb_nt_SetupStart + state->setup_count < smb_nt_SetupStart) || - (smb_nt_SetupStart + state->setup_count < state->setup_count)) { - goto bad_param; - } - if (smb_nt_SetupStart + state->setup_count > size) { - goto bad_param; - } - memcpy(state->setup, req->vwv+19, state->setup_count); dump_data(10, (uint8 *)state->setup, state->setup_count); } -- cgit From 2719216d60088eb3f10a2e3e968f15e8089b5491 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 8 Nov 2008 17:08:57 +0100 Subject: Consolidate the buffer checks for the reply_trans style functions This is the one where I found the problem that led to 3.2.5. So if there is one checkin in the last year that I would like others to review and *understand*, it is this one :-) Volker --- source3/smbd/ipc.c | 73 ++++++++++++------------------------------------ source3/smbd/nttrans.c | 75 ++++++++++++-------------------------------------- source3/smbd/trans2.c | 75 ++++++++++++-------------------------------------- 3 files changed, 54 insertions(+), 169 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index bf9b1d87c5..649ead4682 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -503,7 +503,6 @@ void reply_trans(struct smb_request *req) unsigned int pscnt; struct trans_state *state; NTSTATUS result; - unsigned int av_size; START_PROFILE(SMBtrans); @@ -513,7 +512,6 @@ void reply_trans(struct smb_request *req) return; } - av_size = smb_len(req->inbuf); dsoff = SVAL(req->vwv+12, 0); dscnt = SVAL(req->vwv+11, 0); psoff = SVAL(req->vwv+10, 0); @@ -559,6 +557,12 @@ void reply_trans(struct smb_request *req) goto bad_param; if (state->total_data) { + + if (trans_oob(state->total_data, 0, dscnt) + || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) { + goto bad_param; + } + /* Can't use talloc here, the core routines do realloc on the * params and data. Out of paranoia, 100 bytes too many. */ state->data = (char *)SMB_MALLOC(state->total_data+100); @@ -573,21 +577,16 @@ void reply_trans(struct smb_request *req) /* null-terminate the slack space */ memset(&state->data[state->total_data], 0, 100); - if (dscnt > state->total_data || - dsoff+dscnt < dsoff) { - goto bad_param; - } - - if (dsoff > av_size || - dscnt > av_size || - dsoff+dscnt > av_size) { - goto bad_param; - } - memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt); } if (state->total_param) { + + if (trans_oob(state->total_param, 0, pscnt) + || trans_oob(smb_len(req->inbuf), psoff, pscnt)) { + goto bad_param; + } + /* Can't use talloc here, the core routines do realloc on the * params and data. Out of paranoia, 100 bytes too many */ state->param = (char *)SMB_MALLOC(state->total_param+100); @@ -603,17 +602,6 @@ void reply_trans(struct smb_request *req) /* null-terminate the slack space */ memset(&state->param[state->total_param], 0, 100); - if (pscnt > state->total_param || - psoff+pscnt < psoff) { - goto bad_param; - } - - if (psoff > av_size || - pscnt > av_size || - psoff+pscnt > av_size) { - goto bad_param; - } - memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt); } @@ -696,7 +684,6 @@ void reply_transs(struct smb_request *req) connection_struct *conn = req->conn; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; - unsigned int av_size; START_PROFILE(SMBtranss); @@ -729,8 +716,6 @@ void reply_transs(struct smb_request *req) if (SVAL(req->vwv+1, 0) < state->total_data) state->total_data = SVAL(req->vwv+1, 0); - av_size = smb_len(req->inbuf); - pcnt = SVAL(req->vwv+2, 0); poff = SVAL(req->vwv+3, 0); pdisp = SVAL(req->vwv+4, 0); @@ -747,41 +732,19 @@ void reply_transs(struct smb_request *req) goto bad_param; if (pcnt) { - if (pdisp > state->total_param || - pcnt > state->total_param || - pdisp+pcnt > state->total_param || - pdisp+pcnt < pdisp) { - goto bad_param; - } - - if (poff > av_size || - pcnt > av_size || - poff+pcnt > av_size || - poff+pcnt < poff) { + if (trans_oob(state->total_param, pdisp, pcnt) + || trans_oob(smb_len(req->inbuf), poff, pcnt)) { goto bad_param; } - - memcpy(state->param+pdisp,smb_base(req->inbuf)+poff, - pcnt); + memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt); } if (dcnt) { - if (ddisp > state->total_data || - dcnt > state->total_data || - ddisp+dcnt > state->total_data || - ddisp+dcnt < ddisp) { + if (trans_oob(state->total_data, ddisp, dcnt) + || trans_oob(smb_len(req->inbuf), doff, dcnt)) { goto bad_param; } - - if (doff > av_size || - dcnt > av_size || - doff+dcnt > av_size || - doff+dcnt < doff) { - goto bad_param; - } - - memcpy(state->data+ddisp, smb_base(req->inbuf)+doff, - dcnt); + memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt); } if ((state->received_param < state->total_param) || diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b516f02c21..fe2029eeed 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2529,7 +2529,6 @@ void reply_nttrans(struct smb_request *req) uint16 function_code; NTSTATUS result; struct trans_state *state; - uint32_t av_size; START_PROFILE(SMBnttrans); @@ -2539,7 +2538,6 @@ void reply_nttrans(struct smb_request *req) return; } - av_size = smb_len(req->inbuf); pscnt = IVAL(req->vwv+9, 1); psoff = IVAL(req->vwv+11, 1); dscnt = IVAL(req->vwv+13, 1); @@ -2616,6 +2614,12 @@ void reply_nttrans(struct smb_request *req) goto bad_param; if (state->total_data) { + + if (trans_oob(state->total_data, 0, dscnt) + || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) { + goto bad_param; + } + /* Can't use talloc here, the core routines do realloc on the * params and data. */ if ((state->data = (char *)SMB_MALLOC(state->total_data)) == NULL) { @@ -2627,21 +2631,16 @@ void reply_nttrans(struct smb_request *req) return; } - if (dscnt > state->total_data || - dsoff+dscnt < dsoff) { - goto bad_param; - } - - if (dsoff > av_size || - dscnt > av_size || - dsoff+dscnt > av_size) { - goto bad_param; - } - memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt); } if (state->total_param) { + + if (trans_oob(state->total_param, 0, pscnt) + || trans_oob(smb_len(req->inbuf), psoff, pscnt)) { + goto bad_param; + } + /* Can't use talloc here, the core routines do realloc on the * params and data. */ if ((state->param = (char *)SMB_MALLOC(state->total_param)) == NULL) { @@ -2654,17 +2653,6 @@ void reply_nttrans(struct smb_request *req) return; } - if (pscnt > state->total_param || - psoff+pscnt < psoff) { - goto bad_param; - } - - if (psoff > av_size || - pscnt > av_size || - psoff+pscnt > av_size) { - goto bad_param; - } - memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt); } @@ -2741,8 +2729,6 @@ void reply_nttranss(struct smb_request *req) connection_struct *conn = req->conn; uint32_t pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; - uint32_t av_size; - uint32_t size; START_PROFILE(SMBnttranss); @@ -2776,9 +2762,6 @@ void reply_nttranss(struct smb_request *req) state->total_data = IVAL(req->vwv+3, 1); } - size = smb_len(req->inbuf) + 4; - av_size = smb_len(req->inbuf); - pcnt = IVAL(req->vwv+5, 1); poff = IVAL(req->vwv+7, 1); pdisp = IVAL(req->vwv+9, 1); @@ -2795,41 +2778,19 @@ void reply_nttranss(struct smb_request *req) goto bad_param; if (pcnt) { - if (pdisp > state->total_param || - pcnt > state->total_param || - pdisp+pcnt > state->total_param || - pdisp+pcnt < pdisp) { - goto bad_param; - } - - if (poff > av_size || - pcnt > av_size || - poff+pcnt > av_size || - poff+pcnt < poff) { + if (trans_oob(state->total_param, pdisp, pcnt) + || trans_oob(smb_len(req->inbuf), poff, pcnt)) { goto bad_param; } - - memcpy(state->param+pdisp, smb_base(req->inbuf)+poff, - pcnt); + memcpy(state->param+pdisp, smb_base(req->inbuf)+poff,pcnt); } if (dcnt) { - if (ddisp > state->total_data || - dcnt > state->total_data || - ddisp+dcnt > state->total_data || - ddisp+dcnt < ddisp) { + if (trans_oob(state->total_data, ddisp, dcnt) + || trans_oob(smb_len(req->inbuf), doff, dcnt)) { goto bad_param; } - - if (doff > av_size || - dcnt > av_size || - doff+dcnt > av_size || - doff+dcnt < doff) { - goto bad_param; - } - - memcpy(state->data+ddisp, smb_base(req->inbuf)+doff, - dcnt); + memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt); } if ((state->received_param < state->total_param) || diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3a28bd424f..cc8c61175b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7533,7 +7533,6 @@ void reply_trans2(struct smb_request *req) unsigned int psoff; unsigned int pscnt; unsigned int tran_call; - unsigned int av_size; struct trans_state *state; NTSTATUS result; @@ -7550,7 +7549,6 @@ void reply_trans2(struct smb_request *req) psoff = SVAL(req->vwv+10, 0); pscnt = SVAL(req->vwv+9, 0); tran_call = SVAL(req->vwv+14, 0); - av_size = smb_len(req->inbuf); result = allow_new_trans(conn->pending_trans, req->mid); if (!NT_STATUS_IS_OK(result)) { @@ -7632,6 +7630,12 @@ void reply_trans2(struct smb_request *req) goto bad_param; if (state->total_data) { + + if (trans_oob(state->total_data, 0, dscnt) + || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) { + goto bad_param; + } + /* Can't use talloc here, the core routines do realloc on the * params and data. */ state->data = (char *)SMB_MALLOC(state->total_data); @@ -7644,21 +7648,16 @@ void reply_trans2(struct smb_request *req) return; } - if (dscnt > state->total_data || - dsoff+dscnt < dsoff) { - goto bad_param; - } - - if (dsoff > av_size || - dscnt > av_size || - dsoff+dscnt > av_size) { - goto bad_param; - } - memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt); } if (state->total_param) { + + if (trans_oob(state->total_param, 0, pscnt) + || trans_oob(smb_len(req->inbuf), psoff, pscnt)) { + goto bad_param; + } + /* Can't use talloc here, the core routines do realloc on the * params and data. */ state->param = (char *)SMB_MALLOC(state->total_param); @@ -7672,17 +7671,6 @@ void reply_trans2(struct smb_request *req) return; } - if (pscnt > state->total_param || - psoff+pscnt < psoff) { - goto bad_param; - } - - if (psoff > av_size || - pscnt > av_size || - psoff+pscnt > av_size) { - goto bad_param; - } - memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt); } @@ -7730,8 +7718,6 @@ void reply_transs2(struct smb_request *req) connection_struct *conn = req->conn; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; - unsigned int size; - unsigned int av_size; START_PROFILE(SMBtranss2); @@ -7743,9 +7729,6 @@ void reply_transs2(struct smb_request *req) return; } - size = smb_len(req->inbuf)+4; - av_size = smb_len(req->inbuf); - for (state = conn->pending_trans; state != NULL; state = state->next) { if (state->mid == req->mid) { @@ -7783,41 +7766,19 @@ void reply_transs2(struct smb_request *req) goto bad_param; if (pcnt) { - if (pdisp > state->total_param || - pcnt > state->total_param || - pdisp+pcnt > state->total_param || - pdisp+pcnt < pdisp) { - goto bad_param; - } - - if (poff > av_size || - pcnt > av_size || - poff+pcnt > av_size || - poff+pcnt < poff) { + if (trans_oob(state->total_param, pdisp, pcnt) + || trans_oob(smb_len(req->inbuf), poff, pcnt)) { goto bad_param; } - - memcpy(state->param+pdisp,smb_base(req->inbuf)+poff, - pcnt); + memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt); } if (dcnt) { - if (ddisp > state->total_data || - dcnt > state->total_data || - ddisp+dcnt > state->total_data || - ddisp+dcnt < ddisp) { + if (trans_oob(state->total_data, ddisp, dcnt) + || trans_oob(smb_len(req->inbuf), doff, dcnt)) { goto bad_param; } - - if (doff > av_size || - dcnt > av_size || - doff+dcnt > av_size || - doff+dcnt < doff) { - goto bad_param; - } - - memcpy(state->data+ddisp, smb_base(req->inbuf)+doff, - dcnt); + memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt); } if ((state->received_param < state->total_param) || -- cgit From a790dcbc4ec2f3b29045ab9919cca5a9ca038e26 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 9 Nov 2008 12:07:57 +0100 Subject: Remove inbuf references from the trans2ioctl code --- source3/smbd/trans2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cc8c61175b..4dc2001042 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7269,8 +7269,8 @@ static void call_trans2ioctl(connection_struct *conn, return; } - if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL) - && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { + if ((SVAL(req->vwv+16, 0) == LMCAT_SPL) + && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) { *ppdata = (char *)SMB_REALLOC(*ppdata, 32); if (*ppdata == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); @@ -7613,8 +7613,8 @@ void reply_trans2(struct smb_request *req) */ if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) - && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL) - && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { + && (SVAL(req->vwv+16, 0) == LMCAT_SPL) + && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) { DEBUG(2,("Got Trans2 DevIOctl jobid\n")); } else { DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count)); -- cgit From 2bb90b7a88518844c1fcb8177cefcbc5b8ecda99 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 9 Nov 2008 17:25:40 +0100 Subject: Remove "conn" parameter from np_open, smb_request contains it --- source3/smbd/nttrans.c | 2 +- source3/smbd/pipes.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index fe2029eeed..18dd7d5c26 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -284,7 +284,7 @@ static void nt_open_pipe(char *fname, connection_struct *conn, /* Strip \\ off the name. */ fname++; - status = np_open(req, conn, fname, &fsp); + status = np_open(req, fname, &fsp); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index b52b1b02d0..261f12cb08 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -78,7 +78,7 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) } #endif - status = np_open(req, conn, fname, &fsp); + status = np_open(req, fname, &fsp); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, -- cgit From 8340d100f6048776f6fd87704a10e7c103714ae7 Mon Sep 17 00:00:00 2001 From: Steven Danneman Date: Sun, 30 Nov 2008 15:51:38 -0800 Subject: Set PRESENT flag when returning NULL [SD]ACL like Windows does. This could also be handled inside each ACL VFS module, by setting the PRESENT flag when a NULL [SD]ACL is created. --- source3/smbd/nttrans.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 18dd7d5c26..777073e6ba 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1587,12 +1587,20 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, status = SMB_VFS_FGET_NT_ACL( fsp, security_info_wanted, &psd); } - if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; } + /* If the SACL/DACL is NULL, but was requested, we mark that it is + * present in the reply to match Windows behavior */ + if (psd->sacl == NULL && + security_info_wanted & SACL_SECURITY_INFORMATION) + psd->type |= SEC_DESC_SACL_PRESENT; + if (psd->dacl == NULL && + security_info_wanted & DACL_SECURITY_INFORMATION) + psd->type |= SEC_DESC_DACL_PRESENT; + sd_size = ndr_size_security_descriptor(psd, 0); DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size)); -- cgit From 7bd7846df7a28b9a066fd4d862de0e4d81aadb86 Mon Sep 17 00:00:00 2001 From: Steven Danneman Date: Sun, 30 Nov 2008 16:26:10 -0800 Subject: Make nt4_compatible_acls() non-static for use by VFS ACL modules. --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 0529d2765e..97fd3b2bbe 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -870,7 +870,7 @@ static void merge_aces( canon_ace **pp_list_head ) Check if we need to return NT4.x compatible ACL entries. ****************************************************************************/ -static bool nt4_compatible_acls(void) +bool nt4_compatible_acls(void) { int compat = lp_acl_compatibility(); -- cgit From 4f0661ace8c83be6686d7f81af77ccf243dbb992 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 1 Dec 2008 17:35:19 +0100 Subject: Fix a debug message, append the correct \n --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4dc2001042..9719d5c386 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1135,7 +1135,7 @@ static uint32 unix_filetype(mode_t mode) return UNIX_TYPE_SOCKET; #endif - DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode)); + DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode)); return UNIX_TYPE_UNKNOWN; } -- cgit From 49a8bd5e14fdb78197fc821fca72f0ba201f5f39 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 1 Dec 2008 13:01:09 -0800 Subject: s3:smbd: '|' isn't allowed in windows filenames metze --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1f99db2de4..d23f9c106e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -119,7 +119,7 @@ static NTSTATUS check_path_syntax_internal(char *path, if (!(*s & 0x80)) { if (!posix_path) { - if (*s <= 0x1f) { + if (*s <= 0x1f || *s == '|') { return NT_STATUS_OBJECT_NAME_INVALID; } switch (*s) { -- cgit From edde763d3f981f9ccdf65feffd85a591fb1708c1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 1 Dec 2008 13:22:55 -0800 Subject: s3:smbd: correctly verify stream names to pass RAW-STREAMS metze --- source3/smbd/reply.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d23f9c106e..a1833b55df 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -52,11 +52,45 @@ static NTSTATUS check_path_syntax_internal(char *path, const char *s = path; NTSTATUS ret = NT_STATUS_OK; bool start_of_name_component = True; + bool stream_started = false; *p_last_component_contains_wcard = False; while (*s) { - if (IS_PATH_SEP(*s,posix_path)) { + if (stream_started) { + switch (*s) { + case '/': + case '\\': + return NT_STATUS_OBJECT_NAME_INVALID; + case ':': + if (s[1] == '\0') { + return NT_STATUS_OBJECT_NAME_INVALID; + } + if (strchr_m(&s[1], ':')) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + if (StrCaseCmp(s, ":$DATA") != 0) { + return NT_STATUS_INVALID_PARAMETER; + } + break; + } + } + + if (!stream_started && *s == ':') { + if (*p_last_component_contains_wcard) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + /* stream names allow more characters than file names */ + stream_started = true; + start_of_name_component = false; + posix_path = true; + + if (s[1] == '\0') { + return NT_STATUS_OBJECT_NAME_INVALID; + } + } + + if (!stream_started && IS_PATH_SEP(*s,posix_path)) { /* * Safe to assume is not the second part of a mb char * as this is handled below. -- cgit From 936037c7dabab1654d4d5e398b2a6ef2d640fc17 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 1 Dec 2008 13:27:47 -0800 Subject: s3:smbd: wildcard characters are allowed in stream names We only check the filename of the basefile now. metze --- source3/smbd/open.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a6867e077c..a8cc5c9118 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -332,6 +332,7 @@ static NTSTATUS open_file(files_struct *fsp, if ((open_access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || (!file_existed && (local_flags & O_CREAT)) || ((local_flags & O_TRUNC) == O_TRUNC) ) { + const char *wild; /* * We can't actually truncate here as the file may be locked. @@ -353,8 +354,17 @@ static NTSTATUS open_file(files_struct *fsp, #endif /* Don't create files with Microsoft wildcard characters. */ + if (fsp->base_fsp) { + /* + * wildcard characters are allowed in stream names + * only test the basefilename + */ + wild = fsp->base_fsp->fsp_name; + } else { + wild = path; + } if ((local_flags & O_CREAT) && !file_existed && - ms_has_wild(path)) { + ms_has_wild(wild)) { return NT_STATUS_OBJECT_NAME_INVALID; } -- cgit From 8edd7752447e178d2e99b23997d475790efb5af2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 1 Dec 2008 13:31:43 -0800 Subject: s3:smbd: construct the correct newname for stream renames The Windows Explorer creates temporary streams and renames them later via SFILEINFO_RENAME_INFO. The newname comes in as ":Stream:$DATA". metze --- source3/smbd/trans2.c | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9719d5c386..8532c85d7b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5353,26 +5353,42 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, return NT_STATUS_NOT_SUPPORTED; } - /* Create the base directory. */ - base_name = talloc_strdup(ctx, fname); - if (!base_name) { - return NT_STATUS_NO_MEMORY; - } - p = strrchr_m(base_name, '/'); - if (p) { - p[1] = '\0'; + if (fsp && fsp->base_fsp) { + if (newname[0] != ':') { + return NT_STATUS_NOT_SUPPORTED; + } + base_name = talloc_asprintf(ctx, "%s%s", + fsp->base_fsp->fsp_name, + newname); + if (!base_name) { + return NT_STATUS_NO_MEMORY; + } } else { - base_name = talloc_strdup(ctx, "./"); + if (is_ntfs_stream_name(newname)) { + return NT_STATUS_NOT_SUPPORTED; + } + + /* Create the base directory. */ + base_name = talloc_strdup(ctx, fname); + if (!base_name) { + return NT_STATUS_NO_MEMORY; + } + p = strrchr_m(base_name, '/'); + if (p) { + p[1] = '\0'; + } else { + base_name = talloc_strdup(ctx, "./"); + if (!base_name) { + return NT_STATUS_NO_MEMORY; + } + } + /* Append the new name. */ + base_name = talloc_asprintf_append(base_name, + "%s", + newname); if (!base_name) { return NT_STATUS_NO_MEMORY; } - } - /* Append the new name. */ - base_name = talloc_asprintf_append(base_name, - "%s", - newname); - if (!base_name) { - return NT_STATUS_NO_MEMORY; } if (fsp) { -- cgit From 4659215a00da0e2ef65d98e6feb020c89563cdba Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 1 Dec 2008 13:35:28 -0800 Subject: s3:smbd: return DELETE_PENDING on path based operations on streams, when the main file was deleted. metze --- source3/smbd/trans2.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8532c85d7b..cc7b87f448 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3999,6 +3999,46 @@ static void call_trans2qfilepathinfo(connection_struct *conn, return; } + if ((conn->fs_capabilities & FILE_NAMED_STREAMS) + && is_ntfs_stream_name(fname)) { + char *base; + SMB_STRUCT_STAT bsbuf; + + status = split_ntfs_stream_name(talloc_tos(), fname, + &base, NULL); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("create_file_unixpath: " + "split_ntfs_stream_name failed: %s\n", + nt_errstr(status))); + reply_nterror(req, status); + return; + } + + SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */ + + if (INFO_LEVEL_IS_UNIX(info_level)) { + /* Always do lstat for UNIX calls. */ + if (SMB_VFS_LSTAT(conn,base,&bsbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno))); + reply_unixerror(req,ERRDOS,ERRbadpath); + return; + } + } else { + if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) { + DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno))); + reply_unixerror(req,ERRDOS,ERRbadpath); + return; + } + } + + fileid = vfs_file_id_from_sbuf(conn, &bsbuf); + get_file_infos(fileid, &delete_pending, NULL); + if (delete_pending) { + reply_nterror(req, NT_STATUS_DELETE_PENDING); + return; + } + } + if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { -- cgit From d1d9dc557434f4eb48cf53269920f43861e8c116 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 1 Dec 2008 13:45:55 -0800 Subject: s3:smbd: write times should be set on the base file instead of the stream name metze --- source3/smbd/trans2.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cc7b87f448..7b051d389f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4957,7 +4957,11 @@ NTSTATUS smb_set_file_time(connection_struct *conn, time_to_asc(convert_timespec_to_time_t(ts[1])) )); if (fsp != NULL) { - set_sticky_write_time_fsp(fsp, ts[1]); + if (fsp->base_fsp) { + set_sticky_write_time_fsp(fsp->base_fsp, ts[1]); + } else { + set_sticky_write_time_fsp(fsp, ts[1]); + } } else { set_sticky_write_time_path(conn, fname, vfs_file_id_from_sbuf(conn, psbuf), @@ -4967,6 +4971,10 @@ NTSTATUS smb_set_file_time(connection_struct *conn, DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n")); + if (fsp && fsp->base_fsp) { + fname = fsp->base_fsp->fsp_name; + } + if(file_ntimes(conn, fname, ts)!=0) { return map_nt_error_from_unix(errno); } -- cgit From 787b0536b7a8d3b13bcb3b0f1d8f7ef7d99f4561 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 1 Dec 2008 13:52:28 -0800 Subject: s3:smbd: only try and fallback to open a directory if it's not a stream open metze --- source3/smbd/open.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a8cc5c9118..420a65b562 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2927,6 +2927,13 @@ NTSTATUS create_file_unixpath(connection_struct *conn, if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { + /* A stream open never opens a directory */ + + if (base_fsp) { + status = NT_STATUS_FILE_IS_A_DIRECTORY; + goto fail; + } + /* * Fail the open if it was explicitly a non-directory * file. -- cgit From e6a2ce970bf24a1ff588ee2f492e47b88145992f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 1 Dec 2008 14:23:30 -0800 Subject: s3:smbd: give the correct error when trying to replace a stream metze --- source3/smbd/reply.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a1833b55df..11c713ab4a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5496,6 +5496,12 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, return NT_STATUS_OBJECT_NAME_COLLISION; } + if(replace_if_exists && dst_exists) { + if (is_ntfs_stream_name(newname)) { + return NT_STATUS_INVALID_PARAMETER; + } + } + if (dst_exists) { struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1); files_struct *dst_fsp = file_find_di_first(fileid); -- cgit From e605fdc81c64eeb37a9d77493df42c0bb010f41f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 1 Dec 2008 14:28:27 -0800 Subject: s3:smbd: close the low level fd of the base_fsp, if the file was created metze --- source3/smbd/open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 420a65b562..f98415ee33 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2852,6 +2852,8 @@ NTSTATUS create_file_unixpath(connection_struct *conn, "%s\n", base, nt_errstr(status))); goto fail; } + /* we don't need to low level fd */ + fd_close(base_fsp); } /* -- cgit