LCOV - code coverage report
Current view: top level - source3/smbd - smb2_ioctl_dfs.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 28 51 54.9 %
Date: 2021-09-23 10:06:22 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Core SMB2 server
       4             : 
       5             :    Copyright (C) Stefan Metzmacher 2009
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "smbd/smbd.h"
      23             : #include "smbd/globals.h"
      24             : #include "../libcli/smb/smb_common.h"
      25             : #include "../lib/util/tevent_ntstatus.h"
      26             : #include "include/ntioctl.h"
      27             : #include "smb2_ioctl_private.h"
      28             : 
      29             : #undef DBGC_CLASS
      30             : #define DBGC_CLASS DBGC_SMB2
      31             : 
      32        6673 : static NTSTATUS fsctl_dfs_get_refers(TALLOC_CTX *mem_ctx,
      33             :                                      struct tevent_context *ev,
      34             :                                      struct connection_struct *conn,
      35             :                                      DATA_BLOB *in_input,
      36             :                                      uint32_t in_max_output,
      37             :                                      DATA_BLOB *out_output)
      38             : {
      39             :         uint16_t in_max_referral_level;
      40             :         DATA_BLOB in_file_name_buffer;
      41             :         char *in_file_name_string;
      42             :         size_t in_file_name_string_size;
      43             :         bool ok;
      44        6673 :         bool overflow = false;
      45             :         NTSTATUS status;
      46             :         int dfs_size;
      47        6673 :         char *dfs_data = NULL;
      48             :         DATA_BLOB output;
      49             : 
      50        6673 :         if (!lp_host_msdfs()) {
      51           0 :                 return NT_STATUS_FS_DRIVER_REQUIRED;
      52             :         }
      53             : 
      54        6673 :         if (in_input->length < (2 + 2)) {
      55           0 :                 return NT_STATUS_INVALID_PARAMETER;
      56             :         }
      57             : 
      58        6673 :         in_max_referral_level = SVAL(in_input->data, 0);
      59        6673 :         in_file_name_buffer.data = in_input->data + 2;
      60        6673 :         in_file_name_buffer.length = in_input->length - 2;
      61             : 
      62       12954 :         ok = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
      63        6673 :                                    in_file_name_buffer.data,
      64             :                                    in_file_name_buffer.length,
      65             :                                    &in_file_name_string,
      66             :                                    &in_file_name_string_size);
      67        6673 :         if (!ok) {
      68           0 :                 return NT_STATUS_ILLEGAL_CHARACTER;
      69             :         }
      70             : 
      71        6673 :         dfs_size = setup_dfs_referral(conn,
      72             :                                       in_file_name_string,
      73             :                                       in_max_referral_level,
      74             :                                       &dfs_data, &status);
      75        6673 :         if (dfs_size < 0) {
      76        4945 :                 return status;
      77             :         }
      78             : 
      79        1728 :         if (dfs_size > in_max_output) {
      80             :                 /*
      81             :                  * TODO: we need a testsuite for this
      82             :                  */
      83           0 :                 overflow = true;
      84           0 :                 dfs_size = in_max_output;
      85             :         }
      86             : 
      87        1728 :         output = data_blob_talloc(mem_ctx, (uint8_t *)dfs_data, dfs_size);
      88        1728 :         SAFE_FREE(dfs_data);
      89        1728 :         if ((dfs_size > 0) && (output.data == NULL)) {
      90           0 :                 return NT_STATUS_NO_MEMORY;
      91             :         }
      92        1728 :         *out_output = output;
      93             : 
      94        1728 :         if (overflow) {
      95           0 :                 return STATUS_BUFFER_OVERFLOW;
      96             :         }
      97        1728 :         return NT_STATUS_OK;
      98             : }
      99             : 
     100        6673 : struct tevent_req *smb2_ioctl_dfs(uint32_t ctl_code,
     101             :                                   struct tevent_context *ev,
     102             :                                   struct tevent_req *req,
     103             :                                   struct smbd_smb2_ioctl_state *state)
     104             : {
     105             :         NTSTATUS status;
     106             : 
     107        6673 :         switch (ctl_code) {
     108        6673 :         case FSCTL_DFS_GET_REFERRALS:
     109        6673 :                 status = fsctl_dfs_get_refers(state, ev, state->smbreq->conn,
     110             :                                               &state->in_input,
     111             :                                               state->in_max_output,
     112             :                                               &state->out_output);
     113        6673 :                 if (!tevent_req_nterror(req, status)) {
     114        1728 :                         tevent_req_done(req);
     115             :                 }
     116        6673 :                 return tevent_req_post(req, ev);
     117             :                 break;
     118           0 :         default: {
     119           0 :                 uint8_t *out_data = NULL;
     120           0 :                 uint32_t out_data_len = 0;
     121             : 
     122           0 :                 if (state->fsp == NULL) {
     123           0 :                         status = NT_STATUS_NOT_SUPPORTED;
     124             :                 } else {
     125           0 :                         status = SMB_VFS_FSCTL(state->fsp,
     126             :                                                state,
     127             :                                                ctl_code,
     128             :                                                state->smbreq->flags2,
     129             :                                                state->in_input.data,
     130             :                                                state->in_input.length,
     131             :                                                &out_data,
     132             :                                                state->in_max_output,
     133             :                                                &out_data_len);
     134           0 :                         state->out_output = data_blob_const(out_data, out_data_len);
     135           0 :                         if (NT_STATUS_IS_OK(status)) {
     136           0 :                                 tevent_req_done(req);
     137           0 :                                 return tevent_req_post(req, ev);
     138             :                         }
     139             :                 }
     140             : 
     141           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
     142           0 :                         if (IS_IPC(state->smbreq->conn)) {
     143           0 :                                 status = NT_STATUS_FS_DRIVER_REQUIRED;
     144             :                         } else {
     145           0 :                                 status = NT_STATUS_INVALID_DEVICE_REQUEST;
     146             :                         }
     147             :                 }
     148             : 
     149           0 :                 tevent_req_nterror(req, status);
     150           0 :                 return tevent_req_post(req, ev);
     151             :                 break;
     152             :         }
     153             :         }
     154             : 
     155             :         tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     156             :         return tevent_req_post(req, ev);
     157             : }

Generated by: LCOV version 1.13