summaryrefslogtreecommitdiff
path: root/source3/smbd/reply.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/reply.c')
-rw-r--r--source3/smbd/reply.c969
1 files changed, 587 insertions, 382 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index ca3a08f872..8db9c623f7 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -32,6 +32,7 @@
#include "fake_file.h"
#include "rpc_client/rpc_client.h"
#include "../librpc/gen_ndr/ndr_spoolss_c.h"
+#include "../librpc/gen_ndr/open_files.h"
#include "rpc_client/cli_spoolss.h"
#include "rpc_client/init_spoolss.h"
#include "rpc_server/rpc_ncacn_np.h"
@@ -39,6 +40,9 @@
#include "libsmb/nmblib.h"
#include "auth.h"
#include "smbprofile.h"
+#include "../lib/tsocket/tsocket.h"
+#include "lib/tevent_wait.h"
+#include "libcli/smb/smb_signing.h"
/****************************************************************************
Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
@@ -314,7 +318,7 @@ size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
char **pp_dest, const char *src, int flags,
NTSTATUS *err, bool *contains_wcard)
{
- return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
+ return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2,
pp_dest, src, smbreq_bufrem(req, src),
flags, err, contains_wcard);
}
@@ -408,13 +412,13 @@ static bool netbios_session_retarget(struct smbd_server_connection *sconn,
char *retarget;
char *p;
int retarget_type = 0x20;
- int retarget_port = 139;
+ int retarget_port = NBT_SMB_PORT;
struct sockaddr_storage retarget_addr;
struct sockaddr_in *in_addr;
bool ret = false;
uint8_t outbuf[10];
- if (get_socket_port(sconn->sock) != 139) {
+ if (get_socket_port(sconn->sock) != NBT_SMB_PORT) {
return false;
}
@@ -481,7 +485,7 @@ static bool netbios_session_retarget(struct smbd_server_connection *sconn,
if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
NULL)) {
- exit_server_cleanly("netbios_session_regarget: srv_send_smb "
+ exit_server_cleanly("netbios_session_retarget: srv_send_smb "
"failed.");
}
@@ -491,6 +495,13 @@ static bool netbios_session_retarget(struct smbd_server_connection *sconn,
return ret;
}
+static void reply_called_name_not_present(char *outbuf)
+{
+ smb_setlen(outbuf, 1);
+ SCVAL(outbuf, 0, 0x83);
+ SCVAL(outbuf, 4, 0x82);
+}
+
/****************************************************************************
Reply to a (netbios-level) special message.
****************************************************************************/
@@ -511,7 +522,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb
smb_setlen(outbuf,0);
switch (msg_type) {
- case 0x81: /* session request */
+ case NBSSrequest: /* session request */
{
/* inbuf_size is guarenteed to be at least 4. */
fstring name1,name2;
@@ -524,18 +535,20 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb
exit_server_cleanly("multiple session request not permitted");
}
- SCVAL(outbuf,0,0x82);
+ SCVAL(outbuf,0,NBSSpositive);
SCVAL(outbuf,3,0);
/* inbuf_size is guaranteed to be at least 4. */
name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
DEBUG(0,("Invalid name length in session request\n"));
+ reply_called_name_not_present(outbuf);
break;
}
name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
DEBUG(0,("Invalid name length in session request\n"));
+ reply_called_name_not_present(outbuf);
break;
}
@@ -546,6 +559,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb
if (name_type1 == -1 || name_type2 == -1) {
DEBUG(0,("Invalid name type in session request\n"));
+ reply_called_name_not_present(outbuf);
break;
}
@@ -562,12 +576,33 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb
*/
if (strequal(name1, "*SMBSERVER ")
|| strequal(name1, "*SMBSERV ")) {
- fstrcpy(name1, sconn->client_id.addr);
+ char *raddr;
+
+ raddr = tsocket_address_inet_addr_string(sconn->remote_address,
+ talloc_tos());
+ if (raddr == NULL) {
+ exit_server_cleanly("could not allocate raddr");
+ }
+
+ fstrcpy(name1, raddr);
}
set_local_machine_name(name1, True);
set_remote_machine_name(name2, True);
+ if (is_ipaddress(sconn->remote_hostname)) {
+ char *p = discard_const_p(char, sconn->remote_hostname);
+
+ talloc_free(p);
+
+ sconn->remote_hostname = talloc_strdup(sconn,
+ get_remote_machine_name());
+ if (sconn->remote_hostname == NULL) {
+ exit_server_cleanly("could not copy remote name");
+ }
+ sconn->conn->remote_hostname = sconn->remote_hostname;
+ }
+
DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
get_local_machine_name(), get_remote_machine_name(),
name_type2));
@@ -575,18 +610,11 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb
if (name_type2 == 'R') {
/* We are being asked for a pathworks session ---
no thanks! */
- SCVAL(outbuf, 0,0x83);
+ reply_called_name_not_present(outbuf);
break;
}
- /* only add the client's machine name to the list
- of possibly valid usernames if we are operating
- in share mode security */
- if (lp_security() == SEC_SHARE) {
- add_session_user(sconn, get_remote_machine_name());
- }
-
- reload_services(sconn->msg_ctx, sconn->sock, True);
+ reload_services(sconn, conn_snum_used, true);
reopen_logs();
sconn->nbt.got_session = true;
@@ -595,17 +623,17 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb
case 0x89: /* session keepalive request
(some old clients produce this?) */
- SCVAL(outbuf,0,SMBkeepalive);
+ SCVAL(outbuf,0,NBSSkeepalive);
SCVAL(outbuf,3,0);
break;
- case 0x82: /* positive session response */
- case 0x83: /* negative session response */
- case 0x84: /* retarget session response */
+ case NBSSpositive: /* positive session response */
+ case NBSSnegative: /* negative session response */
+ case NBSSretarget: /* retarget session response */
DEBUG(0,("Unexpected session response\n"));
break;
- case SMBkeepalive: /* session keepalive */
+ case NBSSkeepalive: /* session keepalive */
default:
return;
}
@@ -614,6 +642,10 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb
msg_type, msg_flags));
srv_send_smb(sconn, outbuf, false, 0, false, NULL);
+
+ if (CVAL(outbuf, 0) != 0x82) {
+ exit_server_cleanly("invalid netbios session");
+ }
return;
}
@@ -632,9 +664,9 @@ void reply_tcon(struct smb_request *req)
int pwlen=0;
NTSTATUS nt_status;
const char *p;
- DATA_BLOB password_blob;
TALLOC_CTX *ctx = talloc_tos();
struct smbd_server_connection *sconn = req->sconn;
+ NTTIME now = timeval_to_nttime(&req->request_time);
START_PROFILE(SMBtcon);
@@ -664,14 +696,10 @@ void reply_tcon(struct smb_request *req)
service = service_buf;
}
- password_blob = data_blob(password, pwlen+1);
-
- conn = make_connection(sconn,service,password_blob,dev,
+ conn = make_connection(sconn, now, service, dev,
req->vuid,&nt_status);
req->conn = conn;
- data_blob_clear_free(&password_blob);
-
if (!conn) {
reply_nterror(req, nt_status);
END_PROFILE(SMBtcon);
@@ -699,7 +727,6 @@ void reply_tcon_and_X(struct smb_request *req)
{
connection_struct *conn = req->conn;
const char *service = NULL;
- DATA_BLOB password;
TALLOC_CTX *ctx = talloc_tos();
/* what the cleint thinks the device is */
char *client_devicetype = NULL;
@@ -709,7 +736,11 @@ void reply_tcon_and_X(struct smb_request *req)
int passlen;
char *path = NULL;
const char *p, *q;
- uint16 tcon_flags;
+ uint16_t tcon_flags;
+ struct smbXsrv_session *session = NULL;
+ NTTIME now = timeval_to_nttime(&req->request_time);
+ bool session_key_updated = false;
+ uint16_t optional_support = 0;
struct smbd_server_connection *sconn = req->sconn;
START_PROFILE(SMBtconX);
@@ -724,10 +755,32 @@ void reply_tcon_and_X(struct smb_request *req)
tcon_flags = SVAL(req->vwv+2, 0);
/* we might have to close an old one */
- if ((tcon_flags & 0x1) && conn) {
- close_cnum(conn,req->vuid);
+ if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
+ struct smbXsrv_tcon *tcon;
+ NTSTATUS status;
+
+ tcon = conn->tcon;
req->conn = NULL;
conn = NULL;
+
+ /*
+ * TODO: cancel all outstanding requests on the tcon
+ */
+ status = smbXsrv_tcon_disconnect(tcon, req->vuid);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("reply_tcon_and_X: "
+ "smbXsrv_tcon_disconnect() failed: %s\n",
+ nt_errstr(status)));
+ /*
+ * If we hit this case, there is something completely
+ * wrong, so we better disconnect the transport connection.
+ */
+ END_PROFILE(SMBtconX);
+ exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
+ return;
+ }
+
+ TALLOC_FREE(tcon);
}
if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
@@ -737,27 +790,14 @@ void reply_tcon_and_X(struct smb_request *req)
}
if (sconn->smb1.negprot.encrypted_passwords) {
- password = data_blob_talloc(talloc_tos(), req->buf, passlen);
- if (lp_security() == SEC_SHARE) {
- /*
- * Security = share always has a pad byte
- * after the password.
- */
- p = (const char *)req->buf + passlen + 1;
- } else {
- p = (const char *)req->buf + passlen;
- }
+ p = (const char *)req->buf + passlen;
} else {
- password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
- /* Ensure correct termination */
- password.data[passlen]=0;
p = (const char *)req->buf + passlen + 1;
}
p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
if (path == NULL) {
- data_blob_clear_free(&password);
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
END_PROFILE(SMBtconX);
return;
@@ -770,7 +810,6 @@ void reply_tcon_and_X(struct smb_request *req)
if (*path=='\\') {
q = strchr_m(path+2,'\\');
if (!q) {
- data_blob_clear_free(&password);
reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
END_PROFILE(SMBtconX);
return;
@@ -785,7 +824,6 @@ void reply_tcon_and_X(struct smb_request *req)
MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
if (client_devicetype == NULL) {
- data_blob_clear_free(&password);
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
END_PROFILE(SMBtconX);
return;
@@ -793,13 +831,99 @@ void reply_tcon_and_X(struct smb_request *req)
DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
- conn = make_connection(sconn, service, password, client_devicetype,
+ nt_status = smb1srv_session_lookup(req->sconn->conn,
+ req->vuid, now, &session);
+ if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
+ reply_force_doserror(req, ERRSRV, ERRbaduid);
+ END_PROFILE(SMBtconX);
+ return;
+ }
+ if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
+ reply_nterror(req, nt_status);
+ END_PROFILE(SMBtconX);
+ return;
+ }
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ END_PROFILE(SMBtconX);
+ return;
+ }
+
+ if (session->global->auth_session_info == NULL) {
+ reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ END_PROFILE(SMBtconX);
+ return;
+ }
+
+ /*
+ * If there is no application key defined yet
+ * we create one.
+ *
+ * This means we setup the application key on the
+ * first tcon that happens via the given session.
+ *
+ * Once the application key is defined, it does not
+ * change any more.
+ */
+ if (session->global->application_key.length == 0 &&
+ session->global->signing_key.length > 0)
+ {
+ struct smbXsrv_session *x = session;
+ struct auth_session_info *session_info =
+ session->global->auth_session_info;
+ uint8_t session_key[16];
+
+ ZERO_STRUCT(session_key);
+ memcpy(session_key, x->global->signing_key.data,
+ MIN(x->global->signing_key.length, sizeof(session_key)));
+
+ /*
+ * The application key is truncated/padded to 16 bytes
+ */
+ x->global->application_key = data_blob_talloc(x->global,
+ session_key,
+ sizeof(session_key));
+ ZERO_STRUCT(session_key);
+ if (x->global->application_key.data == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBtconX);
+ return;
+ }
+
+ if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
+ smb_key_derivation(x->global->application_key.data,
+ x->global->application_key.length,
+ x->global->application_key.data);
+ optional_support |= SMB_EXTENDED_SIGNATURES;
+ }
+
+ /*
+ * Place the application key into the session_info
+ */
+ data_blob_clear_free(&session_info->session_key);
+ session_info->session_key = data_blob_dup_talloc(session_info,
+ x->global->application_key);
+ if (session_info->session_key.data == NULL) {
+ data_blob_clear_free(&x->global->application_key);
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBtconX);
+ return;
+ }
+ session_key_updated = true;
+ }
+
+ conn = make_connection(sconn, now, service, client_devicetype,
req->vuid, &nt_status);
req->conn =conn;
- data_blob_clear_free(&password);
-
if (!conn) {
+ if (session_key_updated) {
+ struct smbXsrv_session *x = session;
+ struct auth_session_info *session_info =
+ session->global->auth_session_info;
+ data_blob_clear_free(&x->global->application_key);
+ data_blob_clear_free(&session_info->session_key);
+ }
reply_nterror(req, nt_status);
END_PROFILE(SMBtconX);
return;
@@ -822,7 +946,7 @@ void reply_tcon_and_X(struct smb_request *req)
}
} else {
/* NT sets the fstype of IPC$ to the null string */
- const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
+ const char *fstype = IS_IPC(conn) ? "" : lp_fstype(ctx, SNUM(conn));
if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
/* Return permissions. */
@@ -855,30 +979,32 @@ void reply_tcon_and_X(struct smb_request *req)
/* what does setting this bit do? It is set by NT4 and
may affect the ability to autorun mounted cdroms */
- SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
- (lp_csc_policy(SNUM(conn)) << 2));
+ optional_support |= SMB_SUPPORT_SEARCH_BITS;
+ optional_support |=
+ (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
DEBUG(2,("Serving %s as a Dfs root\n",
- lp_servicename(SNUM(conn)) ));
- SSVAL(req->outbuf, smb_vwv2,
- SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
+ lp_servicename(ctx, SNUM(conn)) ));
+ optional_support |= SMB_SHARE_IN_DFS;
}
+
+ SSVAL(req->outbuf, smb_vwv2, optional_support);
}
+ SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+ SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
DEBUG(3,("tconX service=%s \n",
service));
/* set the incoming and outgoing tid to the just created one */
- SSVAL(req->inbuf,smb_tid,conn->cnum);
+ SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
SSVAL(req->outbuf,smb_tid,conn->cnum);
END_PROFILE(SMBtconX);
req->tid = conn->cnum;
- chain_reply(req);
- return;
}
/****************************************************************************
@@ -950,17 +1076,16 @@ void reply_ioctl(struct smb_request *req)
return;
}
/* Job number */
- if (fsp->print_file) {
- SSVAL(p, 0, fsp->print_file->rap_jobid);
- } else {
- SSVAL(p, 0, 0);
- }
+ SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
+
srvstr_push((char *)req->outbuf, req->flags2, p+2,
- global_myname(), 15,
+ lp_netbios_name(), 15,
STR_TERMINATE|STR_ASCII);
if (conn) {
srvstr_push((char *)req->outbuf, req->flags2,
- p+18, lp_servicename(SNUM(conn)),
+ p+18,
+ lp_servicename(talloc_tos(),
+ SNUM(conn)),
13, STR_TERMINATE|STR_ASCII);
} else {
memset(p+18, 0, 13);
@@ -1087,7 +1212,7 @@ void reply_getatr(struct smb_request *req)
struct smb_filename *smb_fname = NULL;
char *fname = NULL;
int mode=0;
- SMB_OFF_T size=0;
+ off_t size=0;
time_t mtime=0;
const char *p;
NTSTATUS status;
@@ -1246,19 +1371,19 @@ void reply_setatr(struct smb_request *req)
mode = SVAL(req->vwv+0, 0);
mtime = srv_make_unix_date3(req->vwv+1);
- ft.mtime = convert_time_t_to_timespec(mtime);
- status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
- }
-
if (mode != FILE_ATTRIBUTE_NORMAL) {
if (VALID_STAT_OF_DIR(smb_fname->st))
mode |= FILE_ATTRIBUTE_DIRECTORY;
else
mode &= ~FILE_ATTRIBUTE_DIRECTORY;
+ status = check_access(conn, NULL, smb_fname,
+ FILE_WRITE_ATTRIBUTES);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ goto out;
+ }
+
if (file_set_dosmode(conn, smb_fname, mode, NULL,
false) != 0) {
reply_nterror(req, map_nt_error_from_unix(errno));
@@ -1266,6 +1391,13 @@ void reply_setatr(struct smb_request *req)
}
}
+ ft.mtime = convert_time_t_to_timespec(mtime);
+ status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ goto out;
+ }
+
reply_outbuf(req, 0, 0);
DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
@@ -1373,7 +1505,7 @@ void reply_search(struct smb_request *req)
char *directory = NULL;
struct smb_filename *smb_fname = NULL;
char *fname = NULL;
- SMB_OFF_T size;
+ off_t size;
uint32 mode;
struct timespec date;
uint32 dirtype;
@@ -1466,6 +1598,7 @@ void reply_search(struct smb_request *req)
SCVAL(status,0,(dirtype & 0x1F));
nt_status = dptr_create(conn,
+ NULL, /* req */
NULL, /* fsp */
directory,
True,
@@ -1521,7 +1654,7 @@ void reply_search(struct smb_request *req)
if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
char buf[DIR_STRUCT_SIZE];
memcpy(buf,status,21);
- if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
+ if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
goto out;
@@ -1547,8 +1680,8 @@ void reply_search(struct smb_request *req)
/DIR_STRUCT_SIZE));
DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- directory,lp_dontdescend(SNUM(conn))));
- if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
+ directory,lp_dontdescend(ctx, SNUM(conn))));
+ if (in_list(directory, lp_dontdescend(ctx, SNUM(conn)),True)) {
check_descend = True;
}
@@ -1714,7 +1847,7 @@ void reply_open(struct smb_request *req)
struct smb_filename *smb_fname = NULL;
char *fname = NULL;
uint32 fattr=0;
- SMB_OFF_T size = 0;
+ off_t size = 0;
time_t mtime=0;
int info;
files_struct *fsp;
@@ -1793,7 +1926,7 @@ void reply_open(struct smb_request *req)
&info); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(req->mid)) {
+ if (open_was_deferred(req->sconn, req->mid)) {
/* We have re-scheduled this call. */
goto out;
}
@@ -1970,7 +2103,7 @@ void reply_open_and_X(struct smb_request *req)
&smb_action); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(req->mid)) {
+ if (open_was_deferred(req->sconn, req->mid)) {
/* We have re-scheduled this call. */
goto out;
}
@@ -1987,7 +2120,7 @@ void reply_open_and_X(struct smb_request *req)
reply_nterror(req, NT_STATUS_DISK_FULL);
goto out;
}
- retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
+ retval = vfs_set_filelen(fsp, (off_t)allocation_size);
if (retval < 0) {
close_file(req, fsp, ERROR_CLOSE);
reply_nterror(req, NT_STATUS_DISK_FULL);
@@ -2033,6 +2166,9 @@ void reply_open_and_X(struct smb_request *req)
reply_outbuf(req, 15, 0);
}
+ SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+ SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
+
if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
SCVAL(req->outbuf, smb_flg,
CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
@@ -2058,7 +2194,6 @@ void reply_open_and_X(struct smb_request *req)
SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
}
- chain_reply(req);
out:
TALLOC_FREE(smb_fname);
END_PROFILE(SMBopenX);
@@ -2072,32 +2207,55 @@ void reply_open_and_X(struct smb_request *req)
void reply_ulogoffX(struct smb_request *req)
{
struct smbd_server_connection *sconn = req->sconn;
- user_struct *vuser;
+ struct user_struct *vuser;
+ struct smbXsrv_session *session = NULL;
+ NTSTATUS status;
START_PROFILE(SMBulogoffX);
vuser = get_valid_user_struct(sconn, req->vuid);
if(vuser == NULL) {
- DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
- req->vuid));
+ DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
+ (unsigned long long)req->vuid));
+
+ req->vuid = UID_FIELD_INVALID;
+ reply_force_doserror(req, ERRSRV, ERRbaduid);
+ END_PROFILE(SMBulogoffX);
+ return;
}
- /* in user level security we are supposed to close any files
- open by this user */
- if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
- file_close_user(sconn, req->vuid);
+ session = vuser->session;
+ vuser = NULL;
+
+ /*
+ * TODO: cancel all outstanding requests on the session
+ */
+ status = smbXsrv_session_logoff(session);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("reply_ulogoff: "
+ "smbXsrv_session_logoff() failed: %s\n",
+ nt_errstr(status)));
+ /*
+ * If we hit this case, there is something completely
+ * wrong, so we better disconnect the transport connection.
+ */
+ END_PROFILE(SMBulogoffX);
+ exit_server(__location__ ": smbXsrv_session_logoff failed");
+ return;
}
- invalidate_vuid(sconn, req->vuid);
+ TALLOC_FREE(session);
reply_outbuf(req, 2, 0);
+ SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+ SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
- DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
+ DEBUG(3, ("ulogoffX vuid=%llu\n",
+ (unsigned long long)req->vuid));
END_PROFILE(SMBulogoffX);
req->vuid = UID_FIELD_INVALID;
- chain_reply(req);
}
/****************************************************************************
@@ -2192,7 +2350,7 @@ void reply_mknew(struct smb_request *req)
NULL); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(req->mid)) {
+ if (open_was_deferred(req->sconn, req->mid)) {
/* We have re-scheduled this call. */
goto out;
}
@@ -2239,14 +2397,13 @@ void reply_ctemp(struct smb_request *req)
{
connection_struct *conn = req->conn;
struct smb_filename *smb_fname = NULL;
- char *wire_name = NULL;
char *fname = NULL;
uint32 fattr;
files_struct *fsp;
int oplock_request;
+ int tmpfd;
char *s;
NTSTATUS status;
- int i;
TALLOC_CTX *ctx = talloc_tos();
START_PROFILE(SMBctemp);
@@ -2259,86 +2416,77 @@ void reply_ctemp(struct smb_request *req)
fattr = SVAL(req->vwv+0, 0);
oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
- srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
+ srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
goto out;
}
+ if (*fname) {
+ fname = talloc_asprintf(ctx,
+ "%s/TMXXXXXX",
+ fname);
+ } else {
+ fname = talloc_strdup(ctx, "TMXXXXXX");
+ }
- for (i = 0; i < 10; i++) {
- if (*wire_name) {
- fname = talloc_asprintf(ctx,
- "%s/TMP%s",
- wire_name,
- generate_random_str_list(ctx, 5, "0123456789"));
- } else {
- fname = talloc_asprintf(ctx,
- "TMP%s",
- generate_random_str_list(ctx, 5, "0123456789"));
- }
-
- if (!fname) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
- }
+ if (!fname) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ goto out;
+ }
- status = filename_convert(ctx, conn,
+ status = filename_convert(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
0,
NULL,
&smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
- }
- reply_nterror(req, status);
goto out;
}
+ reply_nterror(req, status);
+ goto out;
+ }
- /* Create the file. */
- status = SMB_VFS_CREATE_FILE(
- conn, /* conn */
- req, /* req */
- 0, /* root_dir_fid */
- smb_fname, /* fname */
- FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
- FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
- FILE_CREATE, /* create_disposition*/
- 0, /* create_options */
- fattr, /* file_attributes */
- oplock_request, /* oplock_request */
- 0, /* allocation_size */
- 0, /* private_flags */
- NULL, /* sd */
- NULL, /* ea_list */
- &fsp, /* result */
- NULL); /* pinfo */
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
- TALLOC_FREE(fname);
- TALLOC_FREE(smb_fname);
- continue;
- }
+ tmpfd = mkstemp(smb_fname->base_name);
+ if (tmpfd == -1) {
+ reply_nterror(req, map_nt_error_from_unix(errno));
+ goto out;
+ }
- if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(req->mid)) {
- /* We have re-scheduled this call. */
- goto out;
- }
- reply_openerror(req, status);
- goto out;
- }
+ SMB_VFS_STAT(conn, smb_fname);
- break;
- }
+ /* We should fail if file does not exist. */
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ smb_fname, /* fname */
+ FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
+ FILE_OPEN, /* create_disposition*/
+ 0, /* create_options */
+ fattr, /* file_attributes */
+ oplock_request, /* oplock_request */
+ 0, /* allocation_size */
+ 0, /* private_flags */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ NULL); /* pinfo */
- if (i == 10) {
- /* Collision after 10 times... */
- reply_nterror(req, status);
+ /* close fd from mkstemp() */
+ close(tmpfd);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ if (open_was_deferred(req->sconn, req->mid)) {
+ /* We have re-scheduled this call. */
+ goto out;
+ }
+ reply_openerror(req, status);
goto out;
}
@@ -2379,8 +2527,6 @@ void reply_ctemp(struct smb_request *req)
fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
out:
TALLOC_FREE(smb_fname);
- TALLOC_FREE(fname);
- TALLOC_FREE(wire_name);
END_PROFILE(SMBctemp);
return;
}
@@ -2553,9 +2699,9 @@ static NTSTATUS do_unlink(connection_struct *conn,
}
/* The set is across all open files on this dev/inode pair. */
- if (!set_delete_on_close(fsp, true,
+ if (!set_delete_on_close(fsp, True,
conn->session_info->security_token,
- &conn->session_info->utok)) {
+ conn->session_info->unix_token)) {
close_file(req, fsp, NORMAL_CLOSE);
return NT_STATUS_ACCESS_DENIED;
}
@@ -2813,7 +2959,7 @@ void reply_unlink(struct smb_request *req)
status = unlink_internals(conn, req, dirtype, smb_fname,
path_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(req->mid)) {
+ if (open_was_deferred(req->sconn, req->mid)) {
/* We have re-scheduled this call. */
goto out;
}
@@ -2847,7 +2993,7 @@ static void fail_readraw(void)
Fake (read/write) sendfile. Returns -1 on read or write fail.
****************************************************************************/
-ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
+ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
{
size_t bufsize;
size_t tosend = nread;
@@ -3010,7 +3156,7 @@ static void reply_readbraw_error(struct smbd_server_connection *sconn)
static void send_file_readbraw(connection_struct *conn,
struct smb_request *req,
files_struct *fsp,
- SMB_OFF_T startpos,
+ off_t startpos,
size_t nread,
ssize_t mincount)
{
@@ -3093,9 +3239,9 @@ static void send_file_readbraw(connection_struct *conn,
normal_readbraw:
- outbuf = TALLOC_ARRAY(NULL, char, nread+4);
+ outbuf = talloc_array(NULL, char, nread+4);
if (!outbuf) {
- DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
+ DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
(unsigned)(nread+4)));
reply_readbraw_error(sconn);
return;
@@ -3141,14 +3287,15 @@ void reply_readbraw(struct smb_request *req)
struct smbd_server_connection *sconn = req->sconn;
ssize_t maxcount,mincount;
size_t nread = 0;
- SMB_OFF_T startpos;
+ off_t startpos;
files_struct *fsp;
struct lock_struct lock;
- SMB_OFF_T size = 0;
+ off_t size = 0;
START_PROFILE(SMBreadbraw);
- if (srv_is_signing_active(sconn) || req->encrypted) {
+ if (srv_is_signing_active(sconn) ||
+ is_encrypted_packet(sconn, req->inbuf)) {
exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
"raw reads/writes are disallowed.");
}
@@ -3213,27 +3360,8 @@ void reply_readbraw(struct smb_request *req)
/*
* This is a large offset (64 bit) read.
*/
-#ifdef LARGE_SMB_OFF_T
- startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
-
-#else /* !LARGE_SMB_OFF_T */
-
- /*
- * Ensure we haven't been sent a >32 bit offset.
- */
-
- if(IVAL(req->vwv+8, 0) != 0) {
- DEBUG(0,("reply_readbraw: large offset "
- "(%x << 32) used and we don't support "
- "64 bit offsets.\n",
- (unsigned int)IVAL(req->vwv+8, 0) ));
- reply_readbraw_error(sconn);
- END_PROFILE(SMBreadbraw);
- return;
- }
-
-#endif /* LARGE_SMB_OFF_T */
+ startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
if(startpos < 0) {
DEBUG(0,("reply_readbraw: negative 64 bit "
@@ -3276,9 +3404,9 @@ void reply_readbraw(struct smb_request *req)
nread = 0;
#endif
- DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
+ DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
"min=%lu nread=%lu\n",
- fsp->fnum, (double)startpos,
+ fsp_fnum_dbg(fsp), (double)startpos,
(unsigned long)maxcount,
(unsigned long)mincount,
(unsigned long)nread ) );
@@ -3305,7 +3433,7 @@ void reply_lockread(struct smb_request *req)
connection_struct *conn = req->conn;
ssize_t nread = -1;
char *data;
- SMB_OFF_T startpos;
+ off_t startpos;
size_t numtoread;
NTSTATUS status;
files_struct *fsp;
@@ -3397,8 +3525,8 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
SCVAL(p,0,0); /* pad byte. */
SSVAL(p,1,nread);
- DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
- fsp->fnum, (int)numtoread, (int)nread));
+ DEBUG(3,("lockread %s num=%d nread=%d\n",
+ fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
END_PROFILE(SMBlockread);
return;
@@ -3417,7 +3545,7 @@ void reply_read(struct smb_request *req)
size_t numtoread;
ssize_t nread = 0;
char *data;
- SMB_OFF_T startpos;
+ off_t startpos;
int outsize = 0;
files_struct *fsp;
struct lock_struct lock;
@@ -3489,8 +3617,8 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
SCVAL(smb_buf(req->outbuf),0,1);
SSVAL(smb_buf(req->outbuf),1,nread);
- DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
- fsp->fnum, (int)numtoread, (int)nread ) );
+ DEBUG(3, ("read %s num=%d nread=%d\n",
+ fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
strict_unlock:
SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
@@ -3507,10 +3635,8 @@ static int setup_readX_header(struct smb_request *req, char *outbuf,
size_t smb_maxcnt)
{
int outsize;
- char *data;
outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
- data = smb_buf(outbuf);
memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
@@ -3518,7 +3644,7 @@ static int setup_readX_header(struct smb_request *req, char *outbuf,
SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
SSVAL(outbuf,smb_vwv5,smb_maxcnt);
SSVAL(outbuf,smb_vwv6,
- req_wct_ofs(req)
+ (smb_wct - 4) /* offset from smb header to wct */
+ 1 /* the wct field */
+ 12 * sizeof(uint16_t) /* vwv */
+ 2); /* the buflen field */
@@ -3534,13 +3660,18 @@ static int setup_readX_header(struct smb_request *req, char *outbuf,
****************************************************************************/
static void send_file_readX(connection_struct *conn, struct smb_request *req,
- files_struct *fsp, SMB_OFF_T startpos,
+ files_struct *fsp, off_t startpos,
size_t smb_maxcnt)
{
ssize_t nread = -1;
struct lock_struct lock;
int saved_errno = 0;
+ if(fsp_stat(fsp) == -1) {
+ reply_nterror(req, map_nt_error_from_unix(errno));
+ return;
+ }
+
init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
(uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
&lock);
@@ -3550,6 +3681,16 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
return;
}
+ if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
+ (startpos > fsp->fsp_name->st.st_ex_size)
+ || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
+ /*
+ * We already know that we would do a short read, so don't
+ * try the sendfile() path.
+ */
+ goto nosendfile_read;
+ }
+
/*
* We can only use sendfile on a non-chained packet
* but we can use on a non-oplocked file. tridge proved this
@@ -3557,27 +3698,13 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
*/
if (!req_is_in_chain(req) &&
- !req->encrypted && (fsp->base_fsp == NULL) &&
+ !is_encrypted_packet(req->sconn, req->inbuf) &&
+ (fsp->base_fsp == NULL) &&
(fsp->wcp == NULL) &&
lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
uint8 headerbuf[smb_size + 12 * 2];
DATA_BLOB header;
- if(fsp_stat(fsp) == -1) {
- reply_nterror(req, map_nt_error_from_unix(errno));
- goto strict_unlock;
- }
-
- if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
- (startpos > fsp->fsp_name->st.st_ex_size) ||
- (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
- /*
- * We already know that we would do a short read, so don't
- * try the sendfile() path.
- */
- goto nosendfile_read;
- }
-
/*
* Set up the packet header before send. We
* assume here the sendfile will work (get the
@@ -3618,8 +3745,8 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
strerror(errno)));
exit_server_cleanly("send_file_readX: fake_sendfile failed");
}
- DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
- fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+ DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
+ fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
/* No outbuf here means successful sendfile. */
goto strict_unlock;
}
@@ -3642,8 +3769,8 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
goto normal_read;
}
- DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
- fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+ DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
+ fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
/* Deal with possible short send. */
if (nread != smb_maxcnt + sizeof(headerbuf)) {
@@ -3696,6 +3823,8 @@ normal_read:
nosendfile_read:
reply_outbuf(req, 12, smb_maxcnt);
+ SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+ SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
saved_errno = errno;
@@ -3709,10 +3838,8 @@ nosendfile_read:
setup_readX_header(req, (char *)req->outbuf, nread);
- DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
- fsp->fnum, (int)smb_maxcnt, (int)nread ) );
-
- chain_reply(req);
+ DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
+ fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
return;
strict_unlock:
@@ -3727,9 +3854,10 @@ nosendfile_read:
void reply_read_and_X(struct smb_request *req)
{
+ struct smbd_server_connection *sconn = req->sconn;
connection_struct *conn = req->conn;
files_struct *fsp;
- SMB_OFF_T startpos;
+ off_t startpos;
size_t smb_maxcnt;
bool big_readX = False;
#if 0
@@ -3765,7 +3893,15 @@ void reply_read_and_X(struct smb_request *req)
return;
}
- if (global_client_caps & CAP_LARGE_READX) {
+ if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
+ (get_remote_arch() == RA_SAMBA)) {
+ /*
+ * This is Samba only behavior (up to Samba 3.6)!
+ *
+ * Windows 2008 R2 ignores the upper_size,
+ * so we do unless unix extentions are active
+ * or "smbclient" is talking to us.
+ */
size_t upper_size = SVAL(req->vwv+7, 0);
smb_maxcnt |= (upper_size<<16);
if (upper_size > 1) {
@@ -3776,7 +3912,8 @@ void reply_read_and_X(struct smb_request *req)
return;
}
/* We currently don't do this on signed or sealed data. */
- if (srv_is_signing_active(req->sconn) || req->encrypted) {
+ if (srv_is_signing_active(req->sconn) ||
+ is_encrypted_packet(req->sconn, req->inbuf)) {
reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
END_PROFILE(SMBreadX);
return;
@@ -3793,28 +3930,10 @@ void reply_read_and_X(struct smb_request *req)
}
if (req->wct == 12) {
-#ifdef LARGE_SMB_OFF_T
/*
* This is a large offset (64 bit) read.
*/
- startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
-
-#else /* !LARGE_SMB_OFF_T */
-
- /*
- * Ensure we haven't been sent a >32 bit offset.
- */
-
- if(IVAL(req->vwv+10, 0) != 0) {
- DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
- "used and we don't support 64 bit offsets.\n",
- (unsigned int)IVAL(req->vwv+10, 0) ));
- END_PROFILE(SMBreadX);
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- return;
- }
-
-#endif /* LARGE_SMB_OFF_T */
+ startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
}
@@ -3870,9 +3989,9 @@ void error_to_writebrawerr(struct smb_request *req)
static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
size_t *len)
{
- uint8_t msgtype = SMBkeepalive;
+ uint8_t msgtype = NBSSkeepalive;
- while (msgtype == SMBkeepalive) {
+ while (msgtype == NBSSkeepalive) {
NTSTATUS status;
status = read_smb_length_return_keepalive(fd, inbuf, timeout,
@@ -3909,8 +4028,8 @@ void reply_writebraw(struct smb_request *req)
ssize_t total_written=0;
size_t numtowrite=0;
size_t tcount;
- SMB_OFF_T startpos;
- char *data=NULL;
+ off_t startpos;
+ const char *data=NULL;
bool write_through;
files_struct *fsp;
struct lock_struct lock;
@@ -3923,7 +4042,7 @@ void reply_writebraw(struct smb_request *req)
* type of SMBwritec, not SMBwriteBraw, as this tells the client
* we're finished.
*/
- SCVAL(req->inbuf,smb_com,SMBwritec);
+ SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
if (srv_is_signing_active(req->sconn)) {
END_PROFILE(SMBwritebraw);
@@ -3969,8 +4088,8 @@ void reply_writebraw(struct smb_request *req)
on whether we are using the core+ or lanman1.0 protocol */
if(get_Protocol() <= PROTOCOL_COREPLUS) {
- numtowrite = SVAL(smb_buf(req->inbuf),-2);
- data = smb_buf(req->inbuf);
+ numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
+ data = smb_buf_const(req->inbuf);
} else {
numtowrite = SVAL(req->vwv+10, 0);
data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
@@ -4001,9 +4120,9 @@ void reply_writebraw(struct smb_request *req)
nwritten = write_file(req,fsp,data,startpos,numtowrite);
}
- DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
+ DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
"wrote=%d sync=%d\n",
- fsp->fnum, (double)startpos, (int)numtowrite,
+ fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
(int)nwritten, (int)write_through));
if (nwritten < (ssize_t)numtowrite) {
@@ -4015,7 +4134,7 @@ void reply_writebraw(struct smb_request *req)
total_written = nwritten;
/* Allocate a buffer of 64k + length. */
- buf = TALLOC_ARRAY(NULL, char, 65540);
+ buf = talloc_array(NULL, char, 65540);
if (!buf) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
error_to_writebrawerr(req);
@@ -4108,9 +4227,9 @@ void reply_writebraw(struct smb_request *req)
goto strict_unlock;
}
- DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
+ DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
"wrote=%d\n",
- fsp->fnum, (double)startpos, (int)numtowrite,
+ fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
(int)total_written));
if (!fsp->print_file) {
@@ -4126,7 +4245,7 @@ void reply_writebraw(struct smb_request *req)
#if RABBIT_PELLET_FIX
/*
* Fix for "rabbit pellet" mode, trigger an early TCP ack by
- * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
+ * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
* JRA.
*/
if (!send_keepalive(req->sconn->sock)) {
@@ -4159,7 +4278,7 @@ void reply_writeunlock(struct smb_request *req)
connection_struct *conn = req->conn;
ssize_t nwritten = -1;
size_t numtowrite;
- SMB_OFF_T startpos;
+ off_t startpos;
const char *data;
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp;
@@ -4249,8 +4368,8 @@ void reply_writeunlock(struct smb_request *req)
SSVAL(req->outbuf,smb_vwv0,nwritten);
- DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
- fsp->fnum, (int)numtowrite, (int)nwritten));
+ DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
+ fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
strict_unlock:
if (numtowrite && !fsp->print_file) {
@@ -4273,7 +4392,7 @@ void reply_write(struct smb_request *req)
connection_struct *conn = req->conn;
size_t numtowrite;
ssize_t nwritten = -1;
- SMB_OFF_T startpos;
+ off_t startpos;
const char *data;
files_struct *fsp;
struct lock_struct lock;
@@ -4334,12 +4453,12 @@ void reply_write(struct smb_request *req)
/*
* This is actually an allocate call, and set EOF. JRA.
*/
- nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
+ nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
if (nwritten < 0) {
reply_nterror(req, NT_STATUS_DISK_FULL);
goto strict_unlock;
}
- nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
+ nwritten = vfs_set_filelen(fsp, (off_t)startpos);
if (nwritten < 0) {
reply_nterror(req, NT_STATUS_DISK_FULL);
goto strict_unlock;
@@ -4376,7 +4495,7 @@ void reply_write(struct smb_request *req)
SSVAL(req->outbuf,smb_err,ERRdiskfull);
}
- DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
+ DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
strict_unlock:
if (!fsp->print_file) {
@@ -4402,8 +4521,11 @@ bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
connection_struct *conn = NULL;
unsigned int doff = 0;
size_t len = smb_len_large(inbuf);
+ struct smbXsrv_tcon *tcon;
+ NTSTATUS status;
+ NTTIME now = 0;
- if (is_encrypted_packet(inbuf)) {
+ if (is_encrypted_packet(sconn, inbuf)) {
/* Can't do this on encrypted
* connections. */
return false;
@@ -4420,11 +4542,14 @@ bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
return false;
}
- conn = conn_find(sconn, SVAL(inbuf, smb_tid));
- if (conn == NULL) {
+ status = smb1srv_tcon_lookup(sconn->conn, SVAL(inbuf, smb_tid),
+ now, &tcon);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
return false;
}
+ conn = tcon->compat;
+
if (IS_IPC(conn)) {
DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
return false;
@@ -4482,13 +4607,13 @@ void reply_write_and_X(struct smb_request *req)
connection_struct *conn = req->conn;
files_struct *fsp;
struct lock_struct lock;
- SMB_OFF_T startpos;
+ off_t startpos;
size_t numtowrite;
bool write_through;
ssize_t nwritten;
unsigned int smb_doff;
unsigned int smblen;
- char *data;
+ const char *data;
NTSTATUS status;
int saved_errno = 0;
@@ -4496,8 +4621,7 @@ void reply_write_and_X(struct smb_request *req)
if ((req->wct != 12) && (req->wct != 14)) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- END_PROFILE(SMBwriteX);
- return;
+ goto out;
}
numtowrite = SVAL(req->vwv+10, 0);
@@ -4514,20 +4638,17 @@ void reply_write_and_X(struct smb_request *req)
/* Can't do a recvfile write on IPC$ */
if (IS_IPC(conn)) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- END_PROFILE(SMBwriteX);
- return;
+ goto out;
}
if (numtowrite != req->unread_bytes) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- END_PROFILE(SMBwriteX);
- return;
+ goto out;
}
} else {
if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
smb_doff + numtowrite > smblen) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- END_PROFILE(SMBwriteX);
- return;
+ goto out;
}
}
@@ -4535,12 +4656,10 @@ void reply_write_and_X(struct smb_request *req)
if (IS_IPC(conn)) {
if (req->unread_bytes) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- END_PROFILE(SMBwriteX);
- return;
+ goto out;
}
reply_pipe_write_and_X(req);
- END_PROFILE(SMBwriteX);
- return;
+ goto out;
}
fsp = file_fsp(req, SVAL(req->vwv+2, 0));
@@ -4548,41 +4667,22 @@ void reply_write_and_X(struct smb_request *req)
write_through = BITSETW(req->vwv+7,0);
if (!check_fsp(conn, req, fsp)) {
- END_PROFILE(SMBwriteX);
- return;
+ goto out;
}
if (!CHECK_WRITE(fsp)) {
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- END_PROFILE(SMBwriteX);
- return;
+ goto out;
}
data = smb_base(req->inbuf) + smb_doff;
if(req->wct == 14) {
-#ifdef LARGE_SMB_OFF_T
/*
* This is a large offset (64 bit) write.
*/
- startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
-
-#else /* !LARGE_SMB_OFF_T */
-
- /*
- * Ensure we haven't been sent a >32 bit offset.
- */
-
- if(IVAL(req->vwv+12, 0) != 0) {
- DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
- "used and we don't support 64 bit offsets.\n",
- (unsigned int)IVAL(req->vwv+12, 0) ));
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- END_PROFILE(SMBwriteX);
- return;
- }
+ startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
-#endif /* LARGE_SMB_OFF_T */
}
/* X/Open SMB protocol says that, unlike SMBwrite
@@ -4639,11 +4739,13 @@ void reply_write_and_X(struct smb_request *req)
}
reply_outbuf(req, 6, 0);
+ SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+ SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
SSVAL(req->outbuf,smb_vwv2,nwritten);
SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
- DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
- fsp->fnum, (int)numtowrite, (int)nwritten));
+ DEBUG(3,("writeX %s num=%d wrote=%d\n",
+ fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
status = sync_file(conn, fsp, write_through);
if (!NT_STATUS_IS_OK(status)) {
@@ -4654,10 +4756,18 @@ void reply_write_and_X(struct smb_request *req)
}
END_PROFILE(SMBwriteX);
- chain_reply(req);
return;
out:
+ if (req->unread_bytes) {
+ /* writeX failed. drain socket. */
+ if (drain_socket(req->sconn->sock, req->unread_bytes) !=
+ req->unread_bytes) {
+ smb_panic("failed to drain pending bytes");
+ }
+ req->unread_bytes = 0;
+ }
+
END_PROFILE(SMBwriteX);
return;
}
@@ -4669,8 +4779,8 @@ out:
void reply_lseek(struct smb_request *req)
{
connection_struct *conn = req->conn;
- SMB_OFF_T startpos;
- SMB_OFF_T res= -1;
+ off_t startpos;
+ off_t res= -1;
int mode,umode;
files_struct *fsp;
@@ -4692,7 +4802,7 @@ void reply_lseek(struct smb_request *req)
mode = SVAL(req->vwv+1, 0) & 3;
/* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
- startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
+ startpos = (off_t)IVALS(req->vwv+2, 0);
switch (mode) {
case 0:
@@ -4715,7 +4825,7 @@ void reply_lseek(struct smb_request *req)
if (umode == SEEK_END) {
if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
if(errno == EINVAL) {
- SMB_OFF_T current_pos = startpos;
+ off_t current_pos = startpos;
if(fsp_stat(fsp) == -1) {
reply_nterror(req,
@@ -4742,8 +4852,8 @@ void reply_lseek(struct smb_request *req)
reply_outbuf(req, 2, 0);
SIVAL(req->outbuf,smb_vwv0,res);
- DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
- fsp->fnum, (double)startpos, (double)res, mode));
+ DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
+ fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
END_PROFILE(SMBlseek);
return;
@@ -4812,9 +4922,12 @@ void reply_exit(struct smb_request *req)
return;
}
-/****************************************************************************
- Reply to a close - has to deal with closing a directory opened by NT SMB's.
-****************************************************************************/
+struct reply_close_state {
+ files_struct *fsp;
+ struct smb_request *smbreq;
+};
+
+static void do_smb1_close(struct tevent_req *req);
void reply_close(struct smb_request *req)
{
@@ -4841,21 +4954,13 @@ void reply_close(struct smb_request *req)
return;
}
- if(fsp->is_directory) {
- /*
- * Special case - close NT SMB directory handle.
- */
- DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
- status = close_file(req, fsp, NORMAL_CLOSE);
- } else {
- time_t t;
- /*
- * Close ordinary file.
- */
+ DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
+ fsp->is_directory ? "directory" : "file",
+ fsp->fh->fd, fsp_fnum_dbg(fsp),
+ conn->num_files_open));
- DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
- fsp->fh->fd, fsp->fnum,
- conn->num_files_open));
+ if (!fsp->is_directory) {
+ time_t t;
/*
* Take care of any time sent in the close.
@@ -4863,16 +4968,49 @@ void reply_close(struct smb_request *req)
t = srv_make_unix_date3(req->vwv+1);
set_close_write_time(fsp, convert_time_t_to_timespec(t));
+ }
+
+ if (fsp->num_aio_requests != 0) {
+
+ struct reply_close_state *state;
+
+ DEBUG(10, ("closing with aio %u requests pending\n",
+ fsp->num_aio_requests));
/*
- * close_file() returns the unix errno if an error
- * was detected on close - normally this is due to
- * a disk full error. If not then it was probably an I/O error.
+ * We depend on the aio_extra destructor to take care of this
+ * close request once fsp->num_aio_request drops to 0.
*/
- status = close_file(req, fsp, NORMAL_CLOSE);
- }
+ fsp->deferred_close = tevent_wait_send(
+ fsp, fsp->conn->sconn->ev_ctx);
+ if (fsp->deferred_close == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ state = talloc(fsp, struct reply_close_state);
+ if (state == NULL) {
+ TALLOC_FREE(fsp->deferred_close);
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ state->fsp = fsp;
+ state->smbreq = talloc_move(fsp, &req);
+ tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
+ state);
+ END_PROFILE(SMBclose);
+ return;
+ }
+ /*
+ * close_file() returns the unix errno if an error was detected on
+ * close - normally this is due to a disk full error. If not then it
+ * was probably an I/O error.
+ */
+
+ status = close_file(req, fsp, NORMAL_CLOSE);
+done:
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBclose);
@@ -4884,6 +5022,49 @@ void reply_close(struct smb_request *req)
return;
}
+static void do_smb1_close(struct tevent_req *req)
+{
+ struct reply_close_state *state = tevent_req_callback_data(
+ req, struct reply_close_state);
+ struct smb_request *smbreq;
+ NTSTATUS status;
+ int ret;
+
+ ret = tevent_wait_recv(req);
+ TALLOC_FREE(req);
+ if (ret != 0) {
+ DEBUG(10, ("tevent_wait_recv returned %s\n",
+ strerror(ret)));
+ /*
+ * Continue anyway, this should never happen
+ */
+ }
+
+ /*
+ * fsp->smb2_close_request right now is a talloc grandchild of
+ * fsp. When we close_file(fsp), it would go with it. No chance to
+ * reply...
+ */
+ smbreq = talloc_move(talloc_tos(), &state->smbreq);
+
+ status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
+ if (NT_STATUS_IS_OK(status)) {
+ reply_outbuf(smbreq, 0, 0);
+ } else {
+ reply_nterror(smbreq, status);
+ }
+ if (!srv_send_smb(smbreq->sconn,
+ (char *)smbreq->outbuf,
+ true,
+ smbreq->seqnum+1,
+ IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
+ NULL)) {
+ exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
+ "failed.");
+ }
+ TALLOC_FREE(smbreq);
+}
+
/****************************************************************************
Reply to a writeclose (Core+ protocol).
****************************************************************************/
@@ -4894,7 +5075,7 @@ void reply_writeclose(struct smb_request *req)
size_t numtowrite;
ssize_t nwritten = -1;
NTSTATUS close_status = NT_STATUS_OK;
- SMB_OFF_T startpos;
+ off_t startpos;
const char *data;
struct timespec mtime;
files_struct *fsp;
@@ -4952,8 +5133,8 @@ void reply_writeclose(struct smb_request *req)
close_status = close_file(req, fsp, NORMAL_CLOSE);
}
- DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
- fsp->fnum, (int)numtowrite, (int)nwritten,
+ DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
+ fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
conn->num_files_open));
if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
@@ -5012,8 +5193,8 @@ void reply_lock(struct smb_request *req)
count = (uint64_t)IVAL(req->vwv+1, 0);
offset = (uint64_t)IVAL(req->vwv+3, 0);
- DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
- fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
+ DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
+ fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
br_lck = do_lock(req->sconn->msg_ctx,
fsp,
@@ -5083,8 +5264,8 @@ void reply_unlock(struct smb_request *req)
return;
}
- DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
- fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
+ DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
+ fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
reply_outbuf(req, 0, 0);
@@ -5102,21 +5283,41 @@ void reply_unlock(struct smb_request *req)
void reply_tdis(struct smb_request *req)
{
+ NTSTATUS status;
connection_struct *conn = req->conn;
+ struct smbXsrv_tcon *tcon;
+
START_PROFILE(SMBtdis);
if (!conn) {
DEBUG(4,("Invalid connection in tdis\n"));
- reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
+ reply_force_doserror(req, ERRSRV, ERRinvnid);
END_PROFILE(SMBtdis);
return;
}
- conn->used = False;
-
- close_cnum(conn,req->vuid);
+ tcon = conn->tcon;
req->conn = NULL;
+ /*
+ * TODO: cancel all outstanding requests on the tcon
+ */
+ status = smbXsrv_tcon_disconnect(tcon, req->vuid);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("reply_tdis: "
+ "smbXsrv_tcon_disconnect() failed: %s\n",
+ nt_errstr(status)));
+ /*
+ * If we hit this case, there is something completely
+ * wrong, so we better disconnect the transport connection.
+ */
+ END_PROFILE(SMBtdis);
+ exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
+ return;
+ }
+
+ TALLOC_FREE(tcon);
+
reply_outbuf(req, 0, 0);
END_PROFILE(SMBtdis);
return;
@@ -5232,8 +5433,8 @@ void reply_printopen(struct smb_request *req)
reply_outbuf(req, 1, 0);
SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
- DEBUG(3,("openprint fd=%d fnum=%d\n",
- fsp->fh->fd, fsp->fnum));
+ DEBUG(3,("openprint fd=%d %s\n",
+ fsp->fh->fd, fsp_fnum_dbg(fsp)));
END_PROFILE(SMBsplopen);
return;
@@ -5270,8 +5471,8 @@ void reply_printclose(struct smb_request *req)
return;
}
- DEBUG(3,("printclose fd=%d fnum=%d\n",
- fsp->fh->fd,fsp->fnum));
+ DEBUG(3,("printclose fd=%d %s\n",
+ fsp->fh->fd, fsp_fnum_dbg(fsp)));
status = close_file(req, fsp, NORMAL_CLOSE);
@@ -5331,7 +5532,7 @@ void reply_printqueue(struct smb_request *req)
TALLOC_CTX *mem_ctx = talloc_tos();
NTSTATUS status;
WERROR werr;
- const char *sharename = lp_servicename(SNUM(conn));
+ const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
struct rpc_pipe_client *cli = NULL;
struct dcerpc_binding_handle *b = NULL;
struct policy_handle handle;
@@ -5347,7 +5548,7 @@ void reply_printqueue(struct smb_request *req)
status = rpc_pipe_open_interface(conn,
&ndr_table_spoolss.syntax_id,
conn->session_info,
- &conn->sconn->client_id,
+ conn->sconn->remote_address,
conn->sconn->msg_ctx,
&cli);
if (!NT_STATUS_IS_OK(status)) {
@@ -5503,13 +5704,13 @@ void reply_printwrite(struct smb_request *req)
data = (const char *)req->buf + 3;
- if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
+ if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
reply_nterror(req, map_nt_error_from_unix(errno));
END_PROFILE(SMBsplwr);
return;
}
- DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
+ DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
END_PROFILE(SMBsplwr);
return;
@@ -5647,7 +5848,7 @@ void reply_rmdir(struct smb_request *req)
&info); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(req->mid)) {
+ if (open_was_deferred(req->sconn, req->mid)) {
/* We have re-scheduled this call. */
goto out;
}
@@ -5664,7 +5865,7 @@ void reply_rmdir(struct smb_request *req)
if (!set_delete_on_close(fsp, true,
conn->session_info->security_token,
- &conn->session_info->utok)) {
+ conn->session_info->unix_token)) {
close_file(req, fsp, ERROR_CLOSE);
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
goto out;
@@ -5826,9 +6027,9 @@ static void rename_open_files(connection_struct *conn,
files_struct *fsp;
bool did_rename = False;
NTSTATUS status;
- uint32_t new_name_hash;
+ uint32_t new_name_hash = 0;
- for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
+ for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
fsp = file_find_di_next(fsp)) {
/* fsp_name is a relative path under the fsp. To change this for other
sharepaths we need to manipulate relative paths. */
@@ -5840,8 +6041,8 @@ static void rename_open_files(connection_struct *conn,
if (fsp->name_hash != orig_name_hash) {
continue;
}
- DEBUG(10, ("rename_open_files: renaming file fnum %d "
- "(file_id %s) from %s -> %s\n", fsp->fnum,
+ DEBUG(10, ("rename_open_files: renaming file %s "
+ "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
smb_fname_str_dbg(smb_fname_dst)));
@@ -5854,7 +6055,7 @@ static void rename_open_files(connection_struct *conn,
if (!did_rename) {
DEBUG(10, ("rename_open_files: no open files on file_id %s "
- "for %s\n", file_id_string_tos(&lck->id),
+ "for %s\n", file_id_string_tos(&lck->data->id),
smb_fname_str_dbg(smb_fname_dst)));
}
@@ -6180,8 +6381,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
status = NT_STATUS_ACCESS_DENIED;
}
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
- NULL);
+ lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
/*
* We have the file open ourselves, so not being able to get the
@@ -6197,8 +6397,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
"%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
smb_fname_str_dbg(smb_fname_dst)));
- if (!fsp->is_directory &&
- !lp_posix_pathnames() &&
+ if (!lp_posix_pathnames() &&
(lp_map_archive(SNUM(conn)) ||
lp_store_dos_attributes(SNUM(conn)))) {
/* We must set the archive bit on the newly
@@ -6713,7 +6912,7 @@ void reply_mv(struct smb_request *req)
attrs, False, src_has_wcard, dest_has_wcard,
DELETE_ACCESS);
if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(req->mid)) {
+ if (open_was_deferred(req->sconn, req->mid)) {
/* We have re-scheduled this call. */
goto out;
}
@@ -6746,7 +6945,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
bool target_is_directory)
{
struct smb_filename *smb_fname_dst_tmp = NULL;
- SMB_OFF_T ret=-1;
+ off_t ret=-1;
files_struct *fsp1,*fsp2;
uint32 dosattrs;
uint32 new_create_disposition;
@@ -6891,7 +7090,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
goto out;
}
- if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
+ if (ret != (off_t)smb_fname_src->st.st_ex_size) {
status = NT_STATUS_DISK_FULL;
goto out;
}
@@ -7618,8 +7817,8 @@ NTSTATUS smbd_do_locking(struct smb_request *req,
return status;
}
- DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
- fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
+ DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d num_ulocks=%d\n",
+ fsp_fnum_dbg(fsp), (unsigned int)type, num_locks, num_ulocks));
return NT_STATUS_OK;
}
@@ -7687,8 +7886,8 @@ void reply_lockingX(struct smb_request *req)
bool result;
DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
- "for fnum = %d\n", (unsigned int)oplocklevel,
- fsp->fnum ));
+ "for %s\n", (unsigned int)oplocklevel,
+ fsp_fnum_dbg(fsp)));
/*
* Make sure we have granted an exclusive or batch oplock on
@@ -7704,9 +7903,9 @@ void reply_lockingX(struct smb_request *req)
message here - just ignore it. JRA. */
DEBUG(5,("reply_lockingX: Error : oplock break from "
- "client for fnum = %d (oplock=%d) and no "
+ "client for %s (oplock=%d) and no "
"oplock granted on this file (%s).\n",
- fsp->fnum, fsp->oplock_type,
+ fsp_fnum_dbg(fsp), fsp->oplock_type,
fsp_str_dbg(fsp)));
/* if this is a pure oplock break request then don't
@@ -7841,12 +8040,13 @@ void reply_lockingX(struct smb_request *req)
}
reply_outbuf(req, 2, 0);
+ SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+ SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
- DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
- fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
+ DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
+ fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
END_PROFILE(SMBlockingX);
- chain_reply(req);
}
#undef DBGC_CLASS
@@ -7931,15 +8131,20 @@ void reply_setattrE(struct smb_request *req)
goto out;
}
+ if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ goto out;
+ }
+
status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
goto out;
}
- DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
+ DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
" createtime=%u\n",
- fsp->fnum,
+ fsp_fnum_dbg(fsp),
(unsigned int)ft.atime.tv_sec,
(unsigned int)ft.mtime.tv_sec,
(unsigned int)ft.create_time.tv_sec
@@ -8042,7 +8247,7 @@ void reply_getattrE(struct smb_request *req)
}
SSVAL(req->outbuf,smb_vwv10, mode);
- DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
+ DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
END_PROFILE(SMBgetattrE);
return;