static void smbd_smb2_request_getinfo_done(struct tevent_req *subreq) { struct smbd_smb2_request *req = tevent_req_callback_data(subreq, struct smbd_smb2_request); DATA_BLOB outbody; DATA_BLOB outdyn; uint16_t out_output_buffer_offset; DATA_BLOB out_output_buffer = data_blob_null; NTSTATUS status; NTSTATUS call_status = NT_STATUS_OK; NTSTATUS error; /* transport error */ status = smbd_smb2_getinfo_recv(subreq, req, &out_output_buffer, &call_status); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { error = smbd_smb2_request_error(req, status); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(req->sconn, nt_errstr(error)); return; } return; } /* some GetInfo responses set STATUS_BUFFER_OVERFLOW and return partial, but valid data */ if (!(NT_STATUS_IS_OK(call_status) || NT_STATUS_EQUAL(call_status, STATUS_BUFFER_OVERFLOW))) { /* Return a specific error with data. */ error = smbd_smb2_request_error_ex(req, call_status, &out_output_buffer, __location__); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(req->sconn, nt_errstr(error)); return; } return; } out_output_buffer_offset = SMB2_HDR_BODY + 0x08; outbody = data_blob_talloc(req->out.vector, NULL, 0x08); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(req->sconn, nt_errstr(error)); return; } return; } SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */ SSVAL(outbody.data, 0x02, out_output_buffer_offset); /* output buffer offset */ SIVAL(outbody.data, 0x04, out_output_buffer.length); /* output buffer length */ outdyn = out_output_buffer; error = smbd_smb2_request_done_ex(req, call_status, outbody, &outdyn, __location__); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(req->sconn, nt_errstr(error)); return; } }
static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq) { struct smbd_smb2_request *smb2req = tevent_req_callback_data(subreq, struct smbd_smb2_request); uint8_t *outhdr; DATA_BLOB outbody; DATA_BLOB outdyn; uint16_t out_session_flags = 0; uint64_t out_session_id = 0; uint16_t out_security_offset; DATA_BLOB out_security_buffer = data_blob_null; NTSTATUS status; NTSTATUS error; /* transport error */ status = smbd_smb2_session_setup_wrap_recv(subreq, &out_session_flags, smb2req, &out_security_buffer, &out_session_id); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { status = nt_status_squash(status); error = smbd_smb2_request_error(smb2req, status); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(smb2req->xconn, nt_errstr(error)); return; } return; } out_security_offset = SMB2_HDR_BODY + 0x08; outhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req); outbody = smbd_smb2_generate_outbody(smb2req, 0x08); if (outbody.data == NULL) { error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(smb2req->xconn, nt_errstr(error)); return; } return; } SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id); SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */ SSVAL(outbody.data, 0x02, out_session_flags); /* session flags */ SSVAL(outbody.data, 0x04, out_security_offset); /* security buffer offset */ SSVAL(outbody.data, 0x06, out_security_buffer.length); /* security buffer length */ outdyn = out_security_buffer; error = smbd_smb2_request_done_ex(smb2req, status, outbody, &outdyn, __location__); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(smb2req->xconn, nt_errstr(error)); return; } }
NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req) { const uint8_t *inhdr; const uint8_t *inbody; int i = smb2req->current_idx; uint8_t *outhdr; DATA_BLOB outbody; DATA_BLOB outdyn; uint64_t in_session_id; uint8_t in_security_mode; uint16_t in_security_offset; uint16_t in_security_length; DATA_BLOB in_security_buffer; uint16_t out_session_flags; uint64_t out_session_id; uint16_t out_security_offset; DATA_BLOB out_security_buffer = data_blob_null; NTSTATUS status; status = smbd_smb2_request_verify_sizes(smb2req, 0x19); if (!NT_STATUS_IS_OK(status)) { return smbd_smb2_request_error(smb2req, status); } inhdr = (const uint8_t *)smb2req->in.vector[i+0].iov_base; inbody = (const uint8_t *)smb2req->in.vector[i+1].iov_base; in_security_offset = SVAL(inbody, 0x0C); in_security_length = SVAL(inbody, 0x0E); if (in_security_offset != (SMB2_HDR_BODY + smb2req->in.vector[i+1].iov_len)) { return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER); } if (in_security_length > smb2req->in.vector[i+2].iov_len) { return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER); } in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID); in_security_mode = CVAL(inbody, 0x03); in_security_buffer.data = (uint8_t *)smb2req->in.vector[i+2].iov_base; in_security_buffer.length = in_security_length; status = smbd_smb2_session_setup(smb2req, in_session_id, in_security_mode, in_security_buffer, &out_session_flags, &out_security_buffer, &out_session_id); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { status = nt_status_squash(status); return smbd_smb2_request_error(smb2req, status); } out_security_offset = SMB2_HDR_BODY + 0x08; outhdr = (uint8_t *)smb2req->out.vector[i].iov_base; outbody = data_blob_talloc(smb2req->out.vector, NULL, 0x08); if (outbody.data == NULL) { return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY); } SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id); SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */ SSVAL(outbody.data, 0x02, out_session_flags); /* session flags */ SSVAL(outbody.data, 0x04, out_security_offset); /* security buffer offset */ SSVAL(outbody.data, 0x06, out_security_buffer.length); /* security buffer length */ outdyn = out_security_buffer; return smbd_smb2_request_done_ex(smb2req, status, outbody, &outdyn, __location__); }
static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq) { struct smbd_smb2_request *req = tevent_req_callback_data(subreq, struct smbd_smb2_request); const uint8_t *inbody; int i = req->current_idx; uint8_t *outhdr; DATA_BLOB outbody; DATA_BLOB outdyn; uint32_t in_ctl_code; uint64_t in_file_id_persistent; uint64_t in_file_id_volatile; uint32_t out_input_offset; uint32_t out_output_offset; DATA_BLOB out_output_buffer = data_blob_null; NTSTATUS status; NTSTATUS error; /* transport error */ status = smbd_smb2_ioctl_recv(subreq, req, &out_output_buffer); DEBUG(10,("smbd_smb2_request_ioctl_done: smbd_smb2_ioctl_recv returned " "%u status %s\n", (unsigned int)out_output_buffer.length, nt_errstr(status) )); TALLOC_FREE(subreq); if (NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) { /* also ok */ } else if (!NT_STATUS_IS_OK(status)) { error = smbd_smb2_request_error(req, status); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(req->sconn, nt_errstr(error)); return; } return; } out_input_offset = SMB2_HDR_BODY + 0x30; out_output_offset = SMB2_HDR_BODY + 0x30; inbody = (const uint8_t *)req->in.vector[i+1].iov_base; in_ctl_code = IVAL(inbody, 0x04); in_file_id_persistent = BVAL(inbody, 0x08); in_file_id_volatile = BVAL(inbody, 0x10); outhdr = (uint8_t *)req->out.vector[i].iov_base; outbody = data_blob_talloc(req->out.vector, NULL, 0x30); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(req->sconn, nt_errstr(error)); return; } return; } SSVAL(outbody.data, 0x00, 0x30 + 1); /* struct size */ SSVAL(outbody.data, 0x02, 0); /* reserved */ SIVAL(outbody.data, 0x04, in_ctl_code); /* ctl code */ SBVAL(outbody.data, 0x08, in_file_id_persistent); /* file id (persistent) */ SBVAL(outbody.data, 0x10, in_file_id_volatile); /* file id (volatile) */ SIVAL(outbody.data, 0x18, out_input_offset); /* input offset */ SIVAL(outbody.data, 0x1C, 0); /* input count */ SIVAL(outbody.data, 0x20, out_output_offset); /* output offset */ SIVAL(outbody.data, 0x24, out_output_buffer.length); /* output count */ SIVAL(outbody.data, 0x28, 0); /* flags */ SIVAL(outbody.data, 0x2C, 0); /* reserved */ /* * Note: Windows Vista and 2008 send back also the * input from the request. But it was fixed in * Windows 7. */ outdyn = out_output_buffer; error = smbd_smb2_request_done_ex(req, status, outbody, &outdyn, __location__); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(req->sconn, nt_errstr(error)); return; } }
static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq) { struct smbd_smb2_request *req = tevent_req_callback_data(subreq, struct smbd_smb2_request); const uint8_t *inbody; DATA_BLOB outbody; DATA_BLOB outdyn; uint32_t in_ctl_code; uint64_t in_file_id_persistent; uint64_t in_file_id_volatile; uint32_t out_input_offset; uint32_t out_output_offset; DATA_BLOB out_output_buffer = data_blob_null; NTSTATUS status; NTSTATUS error; /* transport error */ bool disconnect = false; status = smbd_smb2_ioctl_recv(subreq, req, &out_output_buffer, &disconnect); DEBUG(10,("smbd_smb2_request_ioctl_done: smbd_smb2_ioctl_recv returned " "%u status %s\n", (unsigned int)out_output_buffer.length, nt_errstr(status) )); TALLOC_FREE(subreq); if (disconnect) { error = status; smbd_server_connection_terminate(req->xconn, nt_errstr(error)); return; } inbody = SMBD_SMB2_IN_BODY_PTR(req); in_ctl_code = IVAL(inbody, 0x04); in_file_id_persistent = BVAL(inbody, 0x08); in_file_id_volatile = BVAL(inbody, 0x10); if (smbd_smb2_ioctl_is_failure(in_ctl_code, status, out_output_buffer.length)) { error = smbd_smb2_request_error(req, status); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(req->xconn, nt_errstr(error)); return; } return; } out_input_offset = SMB2_HDR_BODY + 0x30; out_output_offset = SMB2_HDR_BODY + 0x30; outbody = smbd_smb2_generate_outbody(req, 0x30); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(req->xconn, nt_errstr(error)); return; } return; } SSVAL(outbody.data, 0x00, 0x30 + 1); /* struct size */ SSVAL(outbody.data, 0x02, 0); /* reserved */ SIVAL(outbody.data, 0x04, in_ctl_code); /* ctl code */ SBVAL(outbody.data, 0x08, in_file_id_persistent); /* file id (persistent) */ SBVAL(outbody.data, 0x10, in_file_id_volatile); /* file id (volatile) */ SIVAL(outbody.data, 0x18, out_input_offset); /* input offset */ SIVAL(outbody.data, 0x1C, 0); /* input count */ SIVAL(outbody.data, 0x20, out_output_offset); /* output offset */ SIVAL(outbody.data, 0x24, out_output_buffer.length); /* output count */ SIVAL(outbody.data, 0x28, 0); /* flags */ SIVAL(outbody.data, 0x2C, 0); /* reserved */ /* * Note: Windows Vista and 2008 send back also the * input from the request. But it was fixed in * Windows 7. */ outdyn = out_output_buffer; error = smbd_smb2_request_done_ex(req, status, outbody, &outdyn, __location__); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(req->xconn, nt_errstr(error)); return; } }