NTSTATUS status;
int ret;
- TALLOC_FREE(conn->fde);
+ TALLOC_FREE(conn->smb1.fde);
conn->smb2.event_ctx = smbd_event_context();
return NT_STATUS_NO_MEMORY;
}
+ conn->smb2.sessions.idtree = idr_init(conn);
+ if (conn->smb2.sessions.idtree == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ conn->smb2.sessions.limit = 0x0000FFFE;
+ conn->smb2.sessions.list = NULL;
+
ret = tstream_bsd_existing_socket(conn, smbd_server_fd(),
&conn->smb2.stream);
if (ret == -1) {
NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
SSVAL(outhdr, SMB2_HDR_OPCODE,
SVAL(inhdr, SMB2_HDR_OPCODE));
- SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
+ /* Make up a number for now... JRA. FIXME ! FIXME !*/
+ SSVAL(outhdr, SMB2_HDR_CREDIT, 20);
SIVAL(outhdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
- SIVAL(outhdr, SMB2_HDR_MESSAGE_ID,
- IVAL(inhdr, SMB2_HDR_MESSAGE_ID));
+ SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
+ BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
SIVAL(outhdr, SMB2_HDR_PID,
IVAL(inhdr, SMB2_HDR_PID));
SIVAL(outhdr, SMB2_HDR_TID,
IVAL(inhdr, SMB2_HDR_TID));
- SIVAL(outhdr, SMB2_HDR_SESSION_ID,
- IVAL(inhdr, SMB2_HDR_SESSION_ID));
+ SBVAL(outhdr, SMB2_HDR_SESSION_ID,
+ BVAL(inhdr, SMB2_HDR_SESSION_ID));
memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
/* setup error body header */
return NT_STATUS_OK;
}
-static void smbd_server_connection_terminate(struct smbd_server_connection *conn,
- const char *reason)
+void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
+ const char *reason,
+ const char *location)
{
- DEBUG(10,("smbd_server_connection_terminate: reason[%s]\n", reason));
+ DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
+ reason, location));
exit_server_cleanly(reason);
}
const uint8_t *inhdr;
int i = req->current_idx;
uint16_t opcode;
+ uint32_t flags;
+ NTSTATUS status;
+ NTSTATUS session_status;
inhdr = (const uint8_t *)req->in.vector[i].iov_base;
/* TODO: verify more things */
+ flags = IVAL(inhdr, SMB2_HDR_FLAGS);
opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
DEBUG(10,("smbd_smb2_request_dispatch: opcode[%u]\n", opcode));
+
+#define TMP_SMB2_ALLOWED_FLAGS ( \
+ SMB2_HDR_FLAG_CHAINED | \
+ SMB2_HDR_FLAG_SIGNED | \
+ SMB2_HDR_FLAG_DFS)
+ if ((flags & ~TMP_SMB2_ALLOWED_FLAGS) != 0) {
+ return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+ }
+#undef TMP_SMB2_ALLOWED_FLAGS
+
+ session_status = smbd_smb2_request_check_session(req);
+
+ req->do_signing = false;
+ if (flags & SMB2_HDR_FLAG_SIGNED) {
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+
+ req->do_signing = true;
+ status = smb2_signing_check_pdu(req->session->session_key,
+ &req->in.vector[i], 3);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ } else if (req->session && req->session->do_signing) {
+ return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
+ }
+
switch (opcode) {
case SMB2_OP_NEGPROT:
+ return smbd_smb2_request_process_negprot(req);
+
case SMB2_OP_SESSSETUP:
+ return smbd_smb2_request_process_sesssetup(req);
+
case SMB2_OP_LOGOFF:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ return smbd_smb2_request_process_logoff(req);
+
case SMB2_OP_TCON:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_session(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_process_tcon(req);
+
case SMB2_OP_TDIS:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_process_tdis(req);
+
case SMB2_OP_CREATE:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_process_create(req);
+
case SMB2_OP_CLOSE:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_process_close(req);
+
case SMB2_OP_FLUSH:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_process_flush(req);
+
case SMB2_OP_READ:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_process_read(req);
+
case SMB2_OP_WRITE:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_process_write(req);
+
case SMB2_OP_LOCK:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
+
case SMB2_OP_IOCTL:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_process_ioctl(req);
+
case SMB2_OP_CANCEL:
+ return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
+
case SMB2_OP_KEEPALIVE:
+ return smbd_smb2_request_process_keepalive(req);
+
case SMB2_OP_FIND:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
+
case SMB2_OP_NOTIFY:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
+
case SMB2_OP_GETINFO:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
+
case SMB2_OP_SETINFO:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+ return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
+
case SMB2_OP_BREAK:
+ if (!NT_STATUS_IS_OK(session_status)) {
+ return smbd_smb2_request_error(req, session_status);
+ }
+ status = smbd_smb2_request_check_tcon(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
}
{
struct tevent_req *subreq;
- /* TODO: sign the response here */
-
smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
+ if (req->do_signing) {
+ int i = req->current_idx;
+ NTSTATUS status;
+ status = smb2_signing_sign_pdu(req->session->session_key,
+ &req->out.vector[i], 3);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
+
req->current_idx += 3;
- if (req->current_idx > req->in.vector_count) {
+ if (req->current_idx < req->out.vector_count) {
struct timeval zero = timeval_zero();
subreq = tevent_wakeup_send(req,
req->conn->smb2.event_ctx,
return NT_STATUS_OK;
}
+static void smbd_smb2_request_dispatch_compound(struct tevent_req *subreq)
+{
+ struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
+ struct smbd_smb2_request);
+ struct smbd_server_connection *conn = req->conn;
+ NTSTATUS status;
+
+ tevent_wakeup_recv(subreq);
+ TALLOC_FREE(subreq);
+
+ DEBUG(10,("smbd_smb2_request_dispatch_compound: idx[%d] of %d vectors\n",
+ req->current_idx, req->in.vector_count));
+
+ status = smbd_smb2_request_dispatch(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ smbd_server_connection_terminate(conn, nt_errstr(status));
+ return;
+ }
+}
+
+static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
+{
+ struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
+ struct smbd_smb2_request);
+ struct smbd_server_connection *conn = req->conn;
+ int ret;
+ int sys_errno;
+ TALLOC_CTX *mem_pool;
+
+ ret = tstream_writev_queue_recv(subreq, &sys_errno);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ NTSTATUS status = map_nt_error_from_unix(sys_errno);
+ smbd_server_connection_terminate(conn, nt_errstr(status));
+ return;
+ }
+
+ mem_pool = req->mem_pool;
+ req = NULL;
+ talloc_free(mem_pool);
+}
+
NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
NTSTATUS status,
- DATA_BLOB *info)
+ DATA_BLOB *info,
+ const char *location)
{
uint8_t *outhdr;
uint8_t *outbody;
int i = req->current_idx;
- DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s]%s\n",
- i, nt_errstr(status), info ? " +info" : ""));
+ DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
+ i, nt_errstr(status), info ? " +info" : "",
+ location));
outhdr = (uint8_t *)req->out.vector[i].iov_base;
return smbd_smb2_request_reply(req);
}
-NTSTATUS smbd_smb2_request_error(struct smbd_smb2_request *req,
- NTSTATUS status)
-{
- return smbd_smb2_request_error_ex(req, status, NULL);
-}
-
-NTSTATUS smbd_smb2_request_done(struct smbd_smb2_request *req,
- DATA_BLOB body, DATA_BLOB *dyn)
+NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
+ NTSTATUS status,
+ DATA_BLOB body, DATA_BLOB *dyn,
+ const char *location)
{
uint8_t *outhdr;
uint8_t *outdyn;
int i = req->current_idx;
uint32_t next_command_ofs;
- DEBUG(10,("smbd_smb2_request_done: idx[%d] body[%u] dyn[%s:%u]\n",
- i, (unsigned int)body.length,
+ DEBUG(10,("smbd_smb2_request_done_ex: "
+ "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
+ i, nt_errstr(status), (unsigned int)body.length,
dyn ? "yes": "no",
- (unsigned int)(dyn ? dyn->length : 0)));
+ (unsigned int)(dyn ? dyn->length : 0),
+ location));
if (body.length < 2) {
return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
/* the fallback dynamic buffer */
outdyn = outhdr + SMB2_HDR_BODY + 8;
- next_command_ofs = SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
- SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(NT_STATUS_OK));
+ next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
+ SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
req->out.vector[i+1].iov_base = (void *)body.data;
req->out.vector[i+1].iov_len = body.length;
req->out.vector[i+2].iov_base = (void *)dyn->data;
req->out.vector[i+2].iov_len = dyn->length;
} else {
- req->out.vector[i+2].iov_base = (void *)outdyn;
- req->out.vector[i+2].iov_len = 1;
+ /* the dyn section is already initialized */
}
} else {
req->out.vector[i+2].iov_base = NULL;
return smbd_smb2_request_reply(req);
}
-static void smbd_smb2_request_dispatch_compound(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- struct smbd_server_connection *conn = req->conn;
- NTSTATUS status;
-
- tevent_wakeup_recv(subreq);
- TALLOC_FREE(subreq);
-
- DEBUG(10,("smbd_smb2_request_dispatch_compound: idx[%d] of %d vectors\n",
- req->current_idx, req->in.vector_count));
-
- status = smbd_smb2_request_dispatch(req);
- if (!NT_STATUS_IS_OK(status)) {
- smbd_server_connection_terminate(conn, nt_errstr(status));
- return;
- }
-}
-
-static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- struct smbd_server_connection *conn = req->conn;
- int ret;
- int sys_errno;
- TALLOC_CTX *mem_pool;
-
- ret = tstream_writev_queue_recv(subreq, &sys_errno);
- TALLOC_FREE(subreq);
- if (ret == -1) {
- NTSTATUS status = map_nt_error_from_unix(sys_errno);
- smbd_server_connection_terminate(conn, nt_errstr(status));
- return;
- }
-
- mem_pool = req->mem_pool;
- req = NULL;
- talloc_free(mem_pool);
-}
-
struct smbd_smb2_request_read_state {
size_t missing;
bool asked_for_header;