diff options
-rw-r--r-- | source3/include/proto.h | 20 | ||||
-rw-r--r-- | source4/smb_server/smb/reply.c | 154 | ||||
-rw-r--r-- | source4/smb_server/smb/service.c | 21 |
3 files changed, 125 insertions, 70 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 518c3a7e93..de2847b468 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2337,7 +2337,17 @@ bool cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fnam bool cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst); bool cli_unlink_full(struct cli_state *cli, const char *fname, uint16 attrs); bool cli_unlink(struct cli_state *cli, const char *fname); +struct tevent_req *cli_mkdir_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *dname); +NTSTATUS cli_mkdir_recv(struct tevent_req *req); NTSTATUS cli_mkdir(struct cli_state *cli, const char *dname); +struct tevent_req *cli_rmdir_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *dname); +NTSTATUS cli_rmdir_recv(struct tevent_req *req); NTSTATUS cli_rmdir(struct cli_state *cli, const char *dname); int cli_nt_delete_on_close(struct cli_state *cli, int fnum, bool flag); int cli_nt_create_full(struct cli_state *cli, const char *fname, @@ -2416,7 +2426,17 @@ bool cli_setattrE(struct cli_state *cli, int fd, time_t access_time, time_t write_time); bool cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t); +struct tevent_req *cli_chkpath_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname); +NTSTATUS cli_chkpath_recv(struct tevent_req *req); NTSTATUS cli_chkpath(struct cli_state *cli, const char *path); +struct tevent_req *cli_dskattr_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli); +NTSTATUS cli_dskattr_recv(struct tevent_req *req, int *bsize, int *total, + int *avail); NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail); int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path); NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *blob); diff --git a/source4/smb_server/smb/reply.c b/source4/smb_server/smb/reply.c index 9c4ee993d2..1b309a0c1f 100644 --- a/source4/smb_server/smb/reply.c +++ b/source4/smb_server/smb/reply.c @@ -44,114 +44,168 @@ static void reply_simple_send(struct ntvfs_request *ntvfs) /**************************************************************************** + 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); + + if (con->generic.level == RAW_TCON_TCON) { + con->tcon.out.max_xmit = req->smb_conn->negotiate.max_recv; + con->tcon.out.tid = req->tcon->tid; + } else { + /* TODO: take a look at tconx.in.flags! */ + con->tconx.out.tid = req->tcon->tid; + con->tconx.out.dev_type = talloc_strdup(req, req->tcon->ntvfs->dev_type); + con->tconx.out.fs_type = talloc_strdup(req, req->tcon->ntvfs->fs_type); + } + + /* 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, req->tcon->share_name)); } /**************************************************************************** + 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); + + if (con->generic.level == RAW_TCON_TCON) { + con->tcon.out.max_xmit = req->smb_conn->negotiate.max_recv; + con->tcon.out.tid = req->tcon->tid; + } else { + /* TODO: take a look at tconx.in.flags! */ + con->tconx.out.tid = req->tcon->tid; + con->tconx.out.dev_type = talloc_strdup(req, req->tcon->ntvfs->dev_type); + con->tconx.out.fs_type = talloc_strdup(req, req->tcon->ntvfs->fs_type); + } + + /* 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); - - 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_SETUP_NTVFS_REQUEST(reply_tcon_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC); - smbsrv_chain_reply(req); + /* Invoke NTVFS connection hook */ + SMBSRV_CALL_NTVFS_BACKEND(ntvfs_connect(req->ntvfs, req->tcon->share_name)); } diff --git a/source4/smb_server/smb/service.c b/source4/smb_server/smb/service.c index 52471c09c9..85d169fc13 100644 --- a/source4/smb_server/smb/service.c +++ b/source4/smb_server/smb/service.c @@ -27,6 +27,7 @@ /**************************************************************************** Make a connection, given the snum to connect to, and the vuser of the connecting user if appropriate. + Does note invoke the NTVFS connection hook ****************************************************************************/ static NTSTATUS make_connection_scfg(struct smbsrv_request *req, struct share_config *scfg, @@ -88,23 +89,6 @@ static NTSTATUS make_connection_scfg(struct smbsrv_request *req, goto failed; } - req->ntvfs = ntvfs_request_create(req->tcon->ntvfs, req, - req->session->session_info, - SVAL(req->in.hdr,HDR_PID), - req->request_time, - req, NULL, 0); - if (!req->ntvfs) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - - /* Invoke NTVFS connection hook */ - status = ntvfs_connect(req->ntvfs, scfg->name); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("make_connection: NTVFS make connection failed!\n")); - goto failed; - } - return NT_STATUS_OK; failed: @@ -204,9 +188,6 @@ NTSTATUS smbsrv_tcon_backend(struct smbsrv_request *req, union smb_tcon *con) return status; } - con->tconx.out.tid = req->tcon->tid; - con->tconx.out.dev_type = talloc_strdup(req, req->tcon->ntvfs->dev_type); - con->tconx.out.fs_type = talloc_strdup(req, req->tcon->ntvfs->fs_type); con->tconx.out.options = SMB_SUPPORT_SEARCH_BITS | (share_int_option(req->tcon->ntvfs->config, SHARE_CSC_POLICY, SHARE_CSC_POLICY_DEFAULT) << 2); if (share_bool_option(req->tcon->ntvfs->config, SHARE_MSDFS_ROOT, SHARE_MSDFS_ROOT_DEFAULT) && lp_host_msdfs(req->smb_conn->lp_ctx)) { con->tconx.out.options |= SMB_SHARE_IN_DFS; |