}
+/****************************************************************************
+ Reply to a tcon (async reply)
+****************************************************************************/
+static void reply_tcon_send(struct ntvfs_request *ntvfs)
+{
+ struct smbsrv_request *req;
+ union smb_tcon *con;
+
+ SMBSRV_CHECK_ASYNC_STATUS(con, union smb_tcon);
+
+ /* construct reply */
+ smbsrv_setup_reply(req, 2, 0);
+
+ SSVAL(req->out.vwv, VWV(0), con->tcon.out.max_xmit);
+ SSVAL(req->out.vwv, VWV(1), con->tcon.out.tid);
+ SSVAL(req->out.hdr, HDR_TID, req->tcon->tid);
+
+ smbsrv_send_reply(req);
+}
+
/****************************************************************************
Reply to a tcon.
****************************************************************************/
void smbsrv_reply_tcon(struct smbsrv_request *req)
{
- union smb_tcon con;
+ union smb_tcon *con;
NTSTATUS status;
uint8_t *p;
/* parse request */
SMBSRV_CHECK_WCT(req, 0);
- con.tcon.level = RAW_TCON_TCON;
+ SMBSRV_TALLOC_IO_PTR(con, union smb_tcon);
+
+ con->tcon.level = RAW_TCON_TCON;
p = req->in.data;
- p += req_pull_ascii4(&req->in.bufinfo, &con.tcon.in.service, p, STR_TERMINATE);
- p += req_pull_ascii4(&req->in.bufinfo, &con.tcon.in.password, p, STR_TERMINATE);
- p += req_pull_ascii4(&req->in.bufinfo, &con.tcon.in.dev, p, STR_TERMINATE);
+ p += req_pull_ascii4(&req->in.bufinfo, &con->tcon.in.service, p, STR_TERMINATE);
+ p += req_pull_ascii4(&req->in.bufinfo, &con->tcon.in.password, p, STR_TERMINATE);
+ p += req_pull_ascii4(&req->in.bufinfo, &con->tcon.in.dev, p, STR_TERMINATE);
- if (!con.tcon.in.service || !con.tcon.in.password || !con.tcon.in.dev) {
+ if (!con->tcon.in.service || !con->tcon.in.password || !con->tcon.in.dev) {
smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
return;
}
- /* call backend */
- status = smbsrv_tcon_backend(req, &con);
-
+ /* Instantiate backend */
+ status = smbsrv_tcon_backend(req, con);
if (!NT_STATUS_IS_OK(status)) {
smbsrv_send_error(req, status);
return;
}
- /* construct reply */
- smbsrv_setup_reply(req, 2, 0);
+ SMBSRV_SETUP_NTVFS_REQUEST(reply_tcon_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
- SSVAL(req->out.vwv, VWV(0), con.tcon.out.max_xmit);
- SSVAL(req->out.vwv, VWV(1), con.tcon.out.tid);
- SSVAL(req->out.hdr, HDR_TID, req->tcon->tid);
-
- smbsrv_send_reply(req);
+ /* Invoke NTVFS connection hook */
+ SMBSRV_CALL_NTVFS_BACKEND(ntvfs_connect(req->ntvfs, con));
}
+/****************************************************************************
+ Reply to a tcon and X (async reply)
+****************************************************************************/
+static void reply_tcon_and_X_send(struct ntvfs_request *ntvfs)
+{
+ struct smbsrv_request *req;
+ union smb_tcon *con;
+
+ SMBSRV_CHECK_ASYNC_STATUS(con, union smb_tcon);
+
+ /* construct reply - two variants */
+ if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
+ smbsrv_setup_reply(req, 2, 0);
+
+ SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
+ SSVAL(req->out.vwv, VWV(1), 0);
+
+ req_push_str(req, NULL, con->tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
+ } else {
+ smbsrv_setup_reply(req, 3, 0);
+
+ SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
+ SSVAL(req->out.vwv, VWV(1), 0);
+ SSVAL(req->out.vwv, VWV(2), con->tconx.out.options);
+
+ req_push_str(req, NULL, con->tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
+ req_push_str(req, NULL, con->tconx.out.fs_type, -1, STR_TERMINATE);
+ }
+
+ /* set the incoming and outgoing tid to the just created one */
+ SSVAL(req->in.hdr, HDR_TID, con->tconx.out.tid);
+ SSVAL(req->out.hdr,HDR_TID, con->tconx.out.tid);
+
+ smbsrv_chain_reply(req);
+}
+
/****************************************************************************
Reply to a tcon and X.
****************************************************************************/
void smbsrv_reply_tcon_and_X(struct smbsrv_request *req)
{
NTSTATUS status;
- union smb_tcon con;
+ union smb_tcon *con;
uint8_t *p;
uint16_t passlen;
- con.tconx.level = RAW_TCON_TCONX;
+ SMBSRV_TALLOC_IO_PTR(con, union smb_tcon);
+
+ con->tconx.level = RAW_TCON_TCONX;
/* parse request */
SMBSRV_CHECK_WCT(req, 4);
- con.tconx.in.flags = SVAL(req->in.vwv, VWV(2));
- passlen = SVAL(req->in.vwv, VWV(3));
+ con->tconx.in.flags = SVAL(req->in.vwv, VWV(2));
+ passlen = SVAL(req->in.vwv, VWV(3));
p = req->in.data;
- if (!req_pull_blob(&req->in.bufinfo, p, passlen, &con.tconx.in.password)) {
+ if (!req_pull_blob(&req->in.bufinfo, p, passlen, &con->tconx.in.password)) {
smbsrv_send_error(req, NT_STATUS_ILL_FORMED_PASSWORD);
return;
}
p += passlen;
- p += req_pull_string(&req->in.bufinfo, &con.tconx.in.path, p, -1, STR_TERMINATE);
- p += req_pull_string(&req->in.bufinfo, &con.tconx.in.device, p, -1, STR_ASCII);
+ p += req_pull_string(&req->in.bufinfo, &con->tconx.in.path, p, -1, STR_TERMINATE);
+ p += req_pull_string(&req->in.bufinfo, &con->tconx.in.device, p, -1, STR_ASCII);
- if (!con.tconx.in.path || !con.tconx.in.device) {
+ if (!con->tconx.in.path || !con->tconx.in.device) {
smbsrv_send_error(req, NT_STATUS_BAD_DEVICE_TYPE);
return;
}
- /* call backend */
- status = smbsrv_tcon_backend(req, &con);
-
+ /* Instantiate backend */
+ status = smbsrv_tcon_backend(req, con);
if (!NT_STATUS_IS_OK(status)) {
smbsrv_send_error(req, status);
return;
}
- /* construct reply - two variants */
- if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
- smbsrv_setup_reply(req, 2, 0);
+ SMBSRV_SETUP_NTVFS_REQUEST(reply_tcon_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
-
- req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
- } else {
- smbsrv_setup_reply(req, 3, 0);
-
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
- SSVAL(req->out.vwv, VWV(2), con.tconx.out.options);
-
- req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
- req_push_str(req, NULL, con.tconx.out.fs_type, -1, STR_TERMINATE);
- }
-
- /* set the incoming and outgoing tid to the just created one */
- SSVAL(req->in.hdr, HDR_TID, con.tconx.out.tid);
- SSVAL(req->out.hdr,HDR_TID, con.tconx.out.tid);
-
- smbsrv_chain_reply(req);
+ /* Invoke NTVFS connection hook */
+ SMBSRV_CALL_NTVFS_BACKEND(ntvfs_connect(req->ntvfs, con));
}
SMBSRV_VWV_RESERVED(4, 1);
SSVAL(req->out.vwv, VWV(5), io->readx.out.nread);
SSVAL(req->out.vwv, VWV(6), PTR_DIFF(io->readx.out.data, req->out.hdr));
- SMBSRV_VWV_RESERVED(7, 5);
+ SSVAL(req->out.vwv, VWV(7), (io->readx.out.nread>>16));
+ SMBSRV_VWV_RESERVED(8, 4);
smbsrv_chain_reply(req);
}
/* make sure the data is in bounds */
if (req_data_oob(&req->in.bufinfo, io->writex.in.data, io->writex.in.count)) {
- smbsrv_send_error(req, NT_STATUS_FOOBAR);
+ smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror));
return;
}
struct smbsrv_request *req;
union smb_lpq *lpq;
int i, maxcount;
- const uint_t el_size = 28;
+ const unsigned int el_size = 28;
SMBSRV_CHECK_ASYNC_STATUS(lpq,union smb_lpq);
void smbsrv_reply_lockingX(struct smbsrv_request *req)
{
union smb_lock *lck;
- uint_t total_locks, i;
- uint_t lck_size;
+ unsigned int total_locks, i;
+ unsigned int lck_size;
uint8_t *p;
/* parse request */
/* notice that the word parameters are not word aligned, so we don't use VWV() */
fname_len = SVAL(req->in.vwv, 5);
io->ntcreatex.in.flags = IVAL(req->in.vwv, 7);
- io->ntcreatex.in.root_fid = IVAL(req->in.vwv, 11);
+ io->ntcreatex.in.root_fid.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, 11);
io->ntcreatex.in.access_mask = IVAL(req->in.vwv, 15);
io->ntcreatex.in.alloc_size = BVAL(req->in.vwv, 19);
io->ntcreatex.in.file_attr = IVAL(req->in.vwv, 27);
io->ntcreatex.in.security_flags = CVAL(req->in.vwv, 47);
io->ntcreatex.in.ea_list = NULL;
io->ntcreatex.in.sec_desc = NULL;
+ io->ntcreatex.in.query_maximal_access = false;
+
+ /* we use a couple of bits of the create options internally */
+ if (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_PRIVATE_MASK) {
+ smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
/* we need a neater way to handle this alignment */
if ((req->flags2 & FLAGS2_UNICODE_STRINGS) &&