Changeset 862 for trunk/server/source3/smbd/smb2_server.c
- Timestamp:
- May 13, 2014, 11:39:04 AM (11 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 860
- Property svn:mergeinfo changed
-
trunk/server/source3/smbd/smb2_server.c
r751 r862 928 928 uint64_t message_id = 0; 929 929 uint64_t async_id = 0; 930 struct iovec *outvec = NULL;931 930 932 931 if (!tevent_req_is_in_progress(subreq)) { … … 945 944 /* 946 945 * We're trying to go async in a compound 947 * request chain. This is not allowed. 948 * Cancel the outstanding request. 949 */ 950 bool ok = tevent_req_cancel(req->subreq); 951 if (ok) { 952 return NT_STATUS_OK; 953 } 954 TALLOC_FREE(req->subreq); 955 return smbd_smb2_request_error(req, 956 NT_STATUS_INTERNAL_ERROR); 946 * request chain. 947 * This is only allowed for opens that 948 * cause an oplock break, otherwise it 949 * is not allowed. See [MS-SMB2].pdf 950 * note <194> on Section 3.3.5.2.7. 951 */ 952 const uint8_t *inhdr = 953 (const uint8_t *)req->in.vector[i].iov_base; 954 955 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) { 956 /* 957 * Cancel the outstanding request. 958 */ 959 bool ok = tevent_req_cancel(req->subreq); 960 if (ok) { 961 return NT_STATUS_OK; 962 } 963 TALLOC_FREE(req->subreq); 964 return smbd_smb2_request_error(req, 965 NT_STATUS_INTERNAL_ERROR); 966 } 957 967 } 958 968 … … 963 973 } 964 974 965 if (req->out.vector_count > 4) { 966 /* This is a compound reply. We 967 * must do an interim response 968 * followed by the async response 969 * to match W2K8R2. 975 if (i > 1) { 976 /* 977 * We're going async in a compound 978 * chain after the first request has 979 * already been processed. Send an 980 * interim response containing the 981 * set of replies already generated. 970 982 */ 971 983 status = smb2_send_async_interim_response(req); … … 974 986 } 975 987 976 /* 977 * We're splitting off the last SMB2 978 * request in a compound set, and the 979 * smb2_send_async_interim_response() 980 * call above just sent all the replies 981 * for the previous SMB2 requests in 982 * this compound set. So we're no longer 983 * in the "compound_related_in_progress" 984 * state, and this is no longer a compound 985 * request. 986 */ 987 req->compound_related = false; 988 req->sconn->smb2.compound_related_in_progress = false; 988 req->current_idx = 1; 989 990 /* 991 * Re-arrange the in.vectors to remove what 992 * we just sent. 993 */ 994 memmove(&req->in.vector[1], 995 &req->in.vector[i], 996 sizeof(req->in.vector[0])*(req->in.vector_count - i)); 997 req->in.vector_count = 1 + (req->in.vector_count - i); 998 999 smb2_setup_nbt_length(req->in.vector, req->in.vector_count); 1000 1001 /* Re-arrange the out.vectors to match. */ 1002 memmove(&req->out.vector[1], 1003 &req->out.vector[i], 1004 sizeof(req->out.vector[0])*(req->out.vector_count - i)); 1005 req->out.vector_count = 1 + (req->out.vector_count - i); 1006 1007 if (req->in.vector_count == 4) { 1008 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base; 1009 /* 1010 * We only have one remaining request as 1011 * we've processed everything else. 1012 * This is no longer a compound request. 1013 */ 1014 req->compound_related = false; 1015 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED); 1016 SIVAL(outhdr, SMB2_HDR_FLAGS, flags); 1017 } 989 1018 } 990 1019 991 1020 /* Don't return an intermediate packet on a pipe read/write. */ 992 1021 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) { 993 goto ipc_out;1022 goto out; 994 1023 } 995 1024 … … 1081 1110 /* Note we're going async with this request. */ 1082 1111 req->async = true; 1083 1084 ipc_out:1085 1086 /*1087 * Now manipulate req so that the outstanding async request1088 * is the only one left in the struct smbd_smb2_request.1089 */1090 1091 if (req->current_idx == 1) {1092 /* There was only one. */1093 goto out;1094 }1095 1096 /* Re-arrange the in.vectors. */1097 req->in.vector[1] = req->in.vector[i];1098 req->in.vector[2] = req->in.vector[i+1];1099 req->in.vector[3] = req->in.vector[i+2];1100 req->in.vector_count = 4;1101 /* Reset the new in size. */1102 smb2_setup_nbt_length(req->in.vector, 4);1103 1104 /* Now recreate the out.vectors. */1105 outvec = talloc_zero_array(req, struct iovec, 4);1106 if (!outvec) {1107 return NT_STATUS_NO_MEMORY;1108 }1109 1110 /* 0 is always boilerplate and must1111 * be of size 4 for the length field. */1112 1113 outvec[0].iov_base = req->out.nbt_hdr;1114 outvec[0].iov_len = 4;1115 SIVAL(req->out.nbt_hdr, 0, 0);1116 1117 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {1118 return NT_STATUS_NO_MEMORY;1119 }1120 1121 TALLOC_FREE(req->out.vector);1122 1123 req->out.vector = outvec;1124 1125 req->current_idx = 1;1126 req->out.vector_count = 4;1127 1112 1128 1113 out: … … 1178 1163 uint64_t message_id; 1179 1164 uint64_t async_id; 1165 1166 if (cur->compound_related) { 1167 /* 1168 * Never cancel anything in a compound request. 1169 * Way too hard to deal with the result. 1170 */ 1171 continue; 1172 } 1180 1173 1181 1174 i = cur->current_idx; … … 1361 1354 if (flags & SMB2_HDR_FLAG_CHAINED) { 1362 1355 req->compound_related = true; 1363 req->sconn->smb2.compound_related_in_progress = true;1364 1356 } 1365 1357 … … 1803 1795 return NT_STATUS_NO_MEMORY; 1804 1796 } 1797 1798 if (req->do_signing) { 1799 /* 1800 * We sign each reply as we go along. 1801 * We can do this as smb2_calculate_credits() 1802 * grants zero credits on every part of a 1803 * compound reply except the last one, 1804 * which is signed just before calling 1805 * tstream_writev_queue_send(). 1806 */ 1807 NTSTATUS status; 1808 status = smb2_signing_sign_pdu(req->session->session_key, 1809 &req->out.vector[i], 3); 1810 if (!NT_STATUS_IS_OK(status)) { 1811 TALLOC_FREE(im); 1812 return status; 1813 } 1814 } 1815 1805 1816 tevent_schedule_immediate(im, 1806 1817 req->sconn->smb2.event_ctx, … … 1812 1823 if (req->compound_related) { 1813 1824 req->compound_related = false; 1814 req->sconn->smb2.compound_related_in_progress = false;1815 1825 } 1816 1826 … … 2529 2539 struct tevent_req *subreq; 2530 2540 2531 if (sconn->smb2.compound_related_in_progress) {2532 /*2533 * Can't read another until the related2534 * compound is done.2535 */2536 return NT_STATUS_OK;2537 }2538 2539 2541 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) { 2540 2542 /*
Note:
See TracChangeset
for help on using the changeset viewer.