#include "auth.h"
#include "smbprofile.h"
#include "../lib/tsocket/tsocket.h"
+#include "lib/tevent_wait.h"
/****************************************************************************
Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
tcon_flags = SVAL(req->vwv+2, 0);
/* we might have to close an old one */
- if ((tcon_flags & 0x1) && conn) {
+ if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
struct smbXsrv_tcon *tcon;
NTSTATUS status;
}
} 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));
+ uint16_t optional_support = 0;
if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
/* Return permissions. */
/* 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 */
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);
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;
/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;
}
{
struct smbd_server_connection *sconn = req->sconn;
struct user_struct *vuser;
+ struct smbXsrv_session *session = NULL;
+ NTSTATUS status;
START_PROFILE(SMBulogoffX);
return;
}
- /* in user level security we are supposed to close any files
- open by this user */
- if (vuser != NULL) {
- 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 */
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)
{
return;
}
- if(fsp->is_directory) {
- /*
- * Special case - close NT SMB directory handle.
- */
- DEBUG(3,("close directory %s\n", fsp_fnum_dbg(fsp)));
- 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 %s (numopen=%d)\n",
- fsp->fh->fd, fsp_fnum_dbg(fsp),
- conn->num_files_open));
+ if (!fsp->is_directory) {
+ time_t t;
/*
* Take care of any time sent in the close.
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);
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).
****************************************************************************/
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;