summaryrefslogtreecommitdiff
path: root/source3/smbd/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/process.c')
-rw-r--r--source3/smbd/process.c270
1 files changed, 0 insertions, 270 deletions
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 6167278fcb..8fb45123ad 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -1852,21 +1852,6 @@ size_t req_wct_ofs(struct smb_request *req)
return buf_size - 4;
}
-/*
- * Hack around reply_nterror & friends not being aware of chained requests,
- * generating illegal (i.e. wct==0) chain replies.
- */
-
-static void fixup_chain_error_packet(struct smb_request *req)
-{
- uint8_t *outbuf = req->outbuf;
- req->outbuf = NULL;
- reply_outbuf(req, 2, 0);
- memcpy(req->outbuf, outbuf, smb_wct);
- TALLOC_FREE(outbuf);
- SCVAL(req->outbuf, smb_vwv0, 0xff);
-}
-
/**
* @brief Find the smb_cmd offset of the last command pushed
* @param[in] buf The buffer we're building up
@@ -2248,261 +2233,6 @@ bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
}
/****************************************************************************
- Construct a chained reply and add it to the already made reply
-****************************************************************************/
-
-void chain_reply(struct smb_request *req)
-{
- size_t smblen = smb_len(req->inbuf);
- size_t already_used, length_needed;
- uint8_t chain_cmd;
- uint32_t chain_offset; /* uint32_t to avoid overflow */
-
- uint8_t wct;
- const uint16_t *vwv;
- uint16_t buflen;
- const uint8_t *buf;
-
- return;
-
- if (IVAL(req->outbuf, smb_rcls) != 0) {
- fixup_chain_error_packet(req);
- }
-
- /*
- * Any of the AndX requests and replies have at least a wct of
- * 2. vwv[0] is the next command, vwv[1] is the offset from the
- * beginning of the SMB header to the next wct field.
- *
- * None of the AndX requests put anything valuable in vwv[0] and [1],
- * so we can overwrite it here to form the chain.
- */
-
- if ((req->wct < 2) || (CVAL(req->outbuf, smb_wct) < 2)) {
- if (req->chain_outbuf == NULL) {
- req->chain_outbuf = talloc_realloc(
- req, req->outbuf, uint8_t,
- smb_len(req->outbuf) + 4);
- if (req->chain_outbuf == NULL) {
- smb_panic("talloc failed");
- }
- }
- req->outbuf = NULL;
- goto error;
- }
-
- /*
- * Here we assume that this is the end of the chain. For that we need
- * to set "next command" to 0xff and the offset to 0. If we later find
- * more commands in the chain, this will be overwritten again.
- */
-
- SCVAL(req->outbuf, smb_vwv0, 0xff);
- SCVAL(req->outbuf, smb_vwv0+1, 0);
- SSVAL(req->outbuf, smb_vwv1, 0);
-
- if (req->chain_outbuf == NULL) {
- /*
- * In req->chain_outbuf we collect all the replies. Start the
- * chain by copying in the first reply.
- *
- * We do the realloc because later on we depend on
- * talloc_get_size to determine the length of
- * chain_outbuf. The reply_xxx routines might have
- * over-allocated (reply_pipe_read_and_X used to be such an
- * example).
- */
- req->chain_outbuf = talloc_realloc(
- req, req->outbuf, uint8_t, smb_len(req->outbuf) + 4);
- if (req->chain_outbuf == NULL) {
- smb_panic("talloc failed");
- }
- req->outbuf = NULL;
- } else {
- /*
- * Update smb headers where subsequent chained commands
- * may have updated them.
- */
- SSVAL(req->chain_outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
- SSVAL(req->chain_outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
-
- if (!smb_splice_chain(&req->chain_outbuf, req->outbuf)) {
- goto error;
- }
- TALLOC_FREE(req->outbuf);
- }
-
- /*
- * We use the old request's vwv field to grab the next chained command
- * and offset into the chained fields.
- */
-
- chain_cmd = CVAL(req->vwv+0, 0);
- chain_offset = SVAL(req->vwv+1, 0);
-
- if (chain_cmd == 0xff) {
- /*
- * End of chain, no more requests from the client. So ship the
- * replies.
- */
- smb_setlen((char *)(req->chain_outbuf),
- talloc_get_size(req->chain_outbuf) - 4);
-
- if (!srv_send_smb(req->sconn, (char *)req->chain_outbuf,
- true, req->seqnum+1,
- IS_CONN_ENCRYPTED(req->conn)
- ||req->encrypted,
- &req->pcd)) {
- exit_server_cleanly("chain_reply: srv_send_smb "
- "failed.");
- }
- TALLOC_FREE(req->chain_outbuf);
- req->done = true;
- return;
- }
-
- /* add a new perfcounter for this element of chain */
- SMB_PERFCOUNT_ADD(&req->pcd);
- SMB_PERFCOUNT_SET_OP(&req->pcd, chain_cmd);
- SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, smblen);
-
- /*
- * Check if the client tries to fool us. The chain offset
- * needs to point beyond the current request in the chain, it
- * needs to strictly grow. Otherwise we might be tricked into
- * an endless loop always processing the same request over and
- * over again. We used to assume that vwv and the byte buffer
- * array in a chain are always attached, but OS/2 the
- * Write&X/Read&X chain puts the Read&X vwv array right behind
- * the Write&X vwv chain. The Write&X bcc array is put behind
- * the Read&X vwv array. So now we check whether the chain
- * offset points strictly behind the previous vwv
- * array. req->buf points right after the vwv array of the
- * previous request. See
- * https://bugzilla.samba.org/show_bug.cgi?id=8360 for more
- * information.
- */
-
- already_used = PTR_DIFF(req->buf, smb_base(req->inbuf));
- if (chain_offset <= already_used) {
- goto error;
- }
-
- /*
- * Next check: Make sure the chain offset does not point beyond the
- * overall smb request length.
- */
-
- length_needed = chain_offset+1; /* wct */
- if (length_needed > smblen) {
- goto error;
- }
-
- /*
- * Now comes the pointer magic. Goal here is to set up req->vwv and
- * req->buf correctly again to be able to call the subsequent
- * switch_message(). The chain offset (the former vwv[1]) points at
- * the new wct field.
- */
-
- wct = CVAL(smb_base(req->inbuf), chain_offset);
-
- /*
- * Next consistency check: Make the new vwv array fits in the overall
- * smb request.
- */
-
- length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
- if (length_needed > smblen) {
- goto error;
- }
- vwv = (const uint16_t *)(smb_base(req->inbuf) + chain_offset + 1);
-
- /*
- * Now grab the new byte buffer....
- */
-
- buflen = SVAL(vwv+wct, 0);
-
- /*
- * .. and check that it fits.
- */
-
- length_needed += buflen;
- if (length_needed > smblen) {
- goto error;
- }
- buf = (const uint8_t *)(vwv+wct+1);
-
- req->cmd = chain_cmd;
- req->wct = wct;
- req->vwv = discard_const_p(uint16_t, vwv);
- req->buflen = buflen;
- req->buf = buf;
-
- switch_message(chain_cmd, req);
-
- if (req->outbuf == NULL) {
- /*
- * This happens if the chained command has suspended itself or
- * if it has called srv_send_smb() itself.
- */
- return;
- }
-
- /*
- * We end up here if the chained command was not itself chained or
- * suspended, but for example a close() command. We now need to splice
- * the chained commands' outbuf into the already built up chain_outbuf
- * and ship the result.
- */
- goto done;
-
- error:
- /*
- * We end up here if there's any error in the chain syntax. Report a
- * DOS error, just like Windows does.
- */
- reply_force_doserror(req, ERRSRV, ERRerror);
- fixup_chain_error_packet(req);
-
- done:
- /*
- * This scary statement intends to set the
- * FLAGS2_32_BIT_ERROR_CODES flg2 field in req->chain_outbuf
- * to the value req->outbuf carries
- */
- SSVAL(req->chain_outbuf, smb_flg2,
- (SVAL(req->chain_outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
- | (SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
-
- /*
- * Transfer the error codes from the subrequest to the main one
- */
- SSVAL(req->chain_outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
- SSVAL(req->chain_outbuf, smb_err, SVAL(req->outbuf, smb_err));
-
- if (!smb_splice_chain(&req->chain_outbuf, req->outbuf)) {
- exit_server_cleanly("chain_reply: smb_splice_chain failed\n");
- }
- TALLOC_FREE(req->outbuf);
-
- smb_setlen((char *)(req->chain_outbuf),
- talloc_get_size(req->chain_outbuf) - 4);
-
- show_msg((char *)(req->chain_outbuf));
-
- if (!srv_send_smb(req->sconn, (char *)req->chain_outbuf,
- true, req->seqnum+1,
- IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
- &req->pcd)) {
- exit_server_cleanly("chain_reply: srv_send_smb failed.");
- }
- TALLOC_FREE(req->chain_outbuf);
- req->done = true;
-}
-
-/****************************************************************************
Check if services need reloading.
****************************************************************************/