From 60d36929189eb8c5749431a4d90266b34c26b0c3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 19 Apr 2010 14:32:08 -0700 Subject: Now SMB2 error messages are correctly being returned with the 1 byte data area, smbd_smb2_request_error_ex() must call smbd_smb2_request_done_ex() in order to do the padding correctly on compound replies. Jeremy. --- source3/smbd/smb2_server.c | 100 ++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 51 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index ebf0986315..277a79ff06 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -397,8 +397,9 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req, uint1 struct iovec *current = &vector[idx]; if ((idx + 3) < count) { - /* we have a next command */ - next_command_ofs = SMB2_HDR_BODY + 8; + /* we have a next command - + * setup for the error case. */ + next_command_ofs = SMB2_HDR_BODY + 9; } inhdr = (const uint8_t *)req->in.vector[idx].iov_base; @@ -1270,53 +1271,6 @@ static void smbd_smb2_request_writev_done(struct tevent_req *subreq) } } -NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req, - NTSTATUS status, - 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| at %s\n", - i, nt_errstr(status), info ? " +info" : "", - location)); - - outhdr = (uint8_t *)req->out.vector[i].iov_base; - - SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status)); - - outbody = outhdr + SMB2_HDR_BODY; - SSVAL(outbody, 0, 9); - - req->out.vector[i+1].iov_base = (void *)outbody; - req->out.vector[i+1].iov_len = 8; - - if (info) { - SIVAL(outbody, 0x04, info->length); - req->out.vector[i+2].iov_base = (void *)info->data; - req->out.vector[i+2].iov_len = info->length; - } else { - /* Allocated size of req->out.vector[i].iov_base - * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for - * 1 byte without having to do an alloc. - */ - req->out.vector[i+2].iov_base = ((uint8_t *)outhdr) + - OUTVEC_ALLOC_SIZE - 1; - req->out.vector[i+2].iov_len = 1; - SCVAL(req->out.vector[i+2].iov_base, 0, 0); - } - - /* - * if a request fails, all other remaining - * compounded requests should fail too - */ - req->next_status = NT_STATUS_INVALID_PARAMETER; - - return smbd_smb2_request_reply(req); -} - NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req, NTSTATUS status, DATA_BLOB body, DATA_BLOB *dyn, @@ -1408,8 +1362,6 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req, req->out.vector[i+2].iov_base = (void *)new_dyn; req->out.vector[i+2].iov_len = new_size; - - TALLOC_FREE(old_dyn); } next_command_ofs += pad_size; } @@ -1419,6 +1371,52 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req, return smbd_smb2_request_reply(req); } +NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req, + NTSTATUS status, + DATA_BLOB *info, + const char *location) +{ + DATA_BLOB body; + int i = req->current_idx; + uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base; + + DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n", + i, nt_errstr(status), info ? " +info" : "", + location)); + + body.data = outhdr + SMB2_HDR_BODY; + body.length = 8; + SSVAL(body.data, 0, 9); + + if (info) { + SIVAL(body.data, 0x04, info->length); + } else { + /* Allocated size of req->out.vector[i].iov_base + * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for + * 1 byte without having to do an alloc. + */ + info = talloc_zero_array(req->out.vector, + DATA_BLOB, + 1); + if (!info) { + return NT_STATUS_NO_MEMORY; + } + info->data = ((uint8_t *)outhdr) + + OUTVEC_ALLOC_SIZE - 1; + info->length = 1; + SCVAL(info->data, 0, 0); + } + + /* + * if a request fails, all other remaining + * compounded requests should fail too + */ + req->next_status = NT_STATUS_INVALID_PARAMETER; + + return smbd_smb2_request_done_ex(req, status, body, info, __location__); +} + + struct smbd_smb2_send_oplock_break_state { struct smbd_server_connection *sconn; uint8_t buf[4 + SMB2_HDR_BODY + 0x18]; -- cgit