Ignore:
Timestamp:
May 13, 2014, 11:39:04 AM (11 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update trunk to 3.6.23

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/smbd/smb2_server.c

    r751 r862  
    928928        uint64_t message_id = 0;
    929929        uint64_t async_id = 0;
    930         struct iovec *outvec = NULL;
    931930
    932931        if (!tevent_req_is_in_progress(subreq)) {
     
    945944                /*
    946945                 * 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                }
    957967        }
    958968
     
    963973        }
    964974
    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.
    970982                 */
    971983                status = smb2_send_async_interim_response(req);
     
    974986                }
    975987
    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                }
    9891018        }
    9901019
    9911020        /* Don't return an intermediate packet on a pipe read/write. */
    9921021        if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
    993                 goto ipc_out;
     1022                goto out;
    9941023        }
    9951024
     
    10811110        /* Note we're going async with this request. */
    10821111        req->async = true;
    1083 
    1084   ipc_out:
    1085 
    1086         /*
    1087          * Now manipulate req so that the outstanding async request
    1088          * 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 must
    1111          * 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;
    11271112
    11281113  out:
     
    11781163                uint64_t message_id;
    11791164                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                }
    11801173
    11811174                i = cur->current_idx;
     
    13611354        if (flags & SMB2_HDR_FLAG_CHAINED) {
    13621355                req->compound_related = true;
    1363                 req->sconn->smb2.compound_related_in_progress = true;
    13641356        }
    13651357
     
    18031795                        return NT_STATUS_NO_MEMORY;
    18041796                }
     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
    18051816                tevent_schedule_immediate(im,
    18061817                                        req->sconn->smb2.event_ctx,
     
    18121823        if (req->compound_related) {
    18131824                req->compound_related = false;
    1814                 req->sconn->smb2.compound_related_in_progress = false;
    18151825        }
    18161826
     
    25292539        struct tevent_req *subreq;
    25302540
    2531         if (sconn->smb2.compound_related_in_progress) {
    2532                 /*
    2533                  * Can't read another until the related
    2534                  * compound is done.
    2535                  */
    2536                 return NT_STATUS_OK;
    2537         }
    2538 
    25392541        if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
    25402542                /*
Note: See TracChangeset for help on using the changeset viewer.