Ignore:
Timestamp:
Nov 29, 2012, 1:59:04 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.9

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/server/source3/smbd/smb2_ioctl.c

    r745 r751  
    3030                                               struct tevent_context *ev,
    3131                                               struct smbd_smb2_request *smb2req,
     32                                               struct files_struct *in_fsp,
    3233                                               uint32_t in_ctl_code,
    33                                                uint64_t in_file_id_volatile,
    3434                                               DATA_BLOB in_input,
    3535                                               uint32_t in_max_output,
     
    4242NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req)
    4343{
    44         const uint8_t *inhdr;
     44        NTSTATUS status;
    4545        const uint8_t *inbody;
    4646        int i = req->current_idx;
    47         size_t expected_body_size = 0x39;
    48         size_t body_size;
    4947        uint32_t in_ctl_code;
    5048        uint64_t in_file_id_persistent;
    5149        uint64_t in_file_id_volatile;
     50        struct files_struct *in_fsp = NULL;
    5251        uint32_t in_input_offset;
    5352        uint32_t in_input_length;
     
    5756        struct tevent_req *subreq;
    5857
    59         inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
    60         if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
    61                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
    62         }
    63 
     58        status = smbd_smb2_request_verify_sizes(req, 0x39);
     59        if (!NT_STATUS_IS_OK(status)) {
     60                return smbd_smb2_request_error(req, status);
     61        }
    6462        inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
    65 
    66         body_size = SVAL(inbody, 0x00);
    67         if (body_size != expected_body_size) {
    68                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
    69         }
    7063
    7164        in_ctl_code             = IVAL(inbody, 0x04);
     
    7770        in_flags                = IVAL(inbody, 0x30);
    7871
    79         if (in_input_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
     72        /*
     73         * InputOffset (4 bytes): The offset, in bytes, from the beginning of
     74         * the SMB2 header to the input data buffer. If no input data is
     75         * required for the FSCTL/IOCTL command being issued, the client SHOULD
     76         * set this value to 0.<49>
     77         * <49> If no input data is required for the FSCTL/IOCTL command being
     78         * issued, Windows-based clients set this field to any value.
     79         */
     80        if ((in_input_length > 0)
     81         && (in_input_offset != (SMB2_HDR_BODY + req->in.vector[i+1].iov_len))) {
    8082                return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
    8183        }
     
    8890        in_input_buffer.length = in_input_length;
    8991
    90         if (req->compat_chain_fsp) {
    91                 /* skip check */
    92         } else if (in_file_id_persistent == UINT64_MAX &&
    93                    in_file_id_volatile == UINT64_MAX) {
    94                 /* without a handle */
    95         } else if (in_file_id_persistent != in_file_id_volatile) {
    96                 return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
     92        switch (in_ctl_code) {
     93        case FSCTL_DFS_GET_REFERRALS:
     94        case FSCTL_DFS_GET_REFERRALS_EX:
     95        case FSCTL_PIPE_WAIT:
     96        case FSCTL_VALIDATE_NEGOTIATE_INFO_224:
     97        case FSCTL_VALIDATE_NEGOTIATE_INFO:
     98        case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
     99                /*
     100                 * Some SMB2 specific CtlCodes like FSCTL_DFS_GET_REFERRALS or
     101                 * FSCTL_PIPE_WAIT does not take a file handle.
     102                 *
     103                 * If FileId in the SMB2 Header of the request is not
     104                 * 0xFFFFFFFFFFFFFFFF, then the server MUST fail the request
     105                 * with STATUS_INVALID_PARAMETER.
     106                 */
     107                if (in_file_id_persistent != UINT64_MAX ||
     108                    in_file_id_volatile != UINT64_MAX) {
     109                        return smbd_smb2_request_error(req,
     110                                NT_STATUS_INVALID_PARAMETER);
     111                }
     112                break;
     113        default:
     114                in_fsp = file_fsp_smb2(req, in_file_id_persistent,
     115                                        in_file_id_volatile);
     116                if (in_fsp == NULL) {
     117                        return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
     118                }
     119                break;
    97120        }
    98121
    99122        subreq = smbd_smb2_ioctl_send(req,
    100123                                      req->sconn->smb2.event_ctx,
    101                                       req,
     124                                      req, in_fsp,
    102125                                      in_ctl_code,
    103                                       in_file_id_volatile,
    104126                                      in_input_buffer,
    105127                                      in_max_output_length,
     
    222244                                               struct tevent_context *ev,
    223245                                               struct smbd_smb2_request *smb2req,
     246                                               struct files_struct *fsp,
    224247                                               uint32_t in_ctl_code,
    225                                                uint64_t in_file_id_volatile,
    226248                                               DATA_BLOB in_input,
    227249                                               uint32_t in_max_output,
     
    231253        struct smbd_smb2_ioctl_state *state;
    232254        struct smb_request *smbreq;
    233         files_struct *fsp = NULL;
    234255        struct tevent_req *subreq;
    235256
     
    241262        state->smb2req = smb2req;
    242263        state->smbreq = NULL;
    243         state->fsp = NULL;
     264        state->fsp = fsp;
    244265        state->in_input = in_input;
    245266        state->in_max_output = in_max_output;
    246267        state->out_output = data_blob_null;
    247268
    248         DEBUG(10,("smbd_smb2_ioctl: file_id[0x%016llX]\n",
    249                   (unsigned long long)in_file_id_volatile));
     269        DEBUG(10, ("smbd_smb2_ioctl: ctl_code[0x%08x] %s fnum[%d]\n",
     270                (unsigned)in_ctl_code,
     271                fsp ? fsp_str_dbg(fsp) : "<no handle>",
     272                fsp ? fsp->fnum : -1));
    250273
    251274        smbreq = smbd_smb2_fake_smb_request(smb2req);
     
    254277        }
    255278        state->smbreq = smbreq;
    256 
    257         if (in_file_id_volatile != UINT64_MAX) {
    258                 fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
    259                 if (fsp == NULL) {
    260                         tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
    261                         return tevent_req_post(req, ev);
    262                 }
    263                 if (smbreq->conn != fsp->conn) {
    264                         tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
    265                         return tevent_req_post(req, ev);
    266                 }
    267                 if (smb2req->session->vuid != fsp->vuid) {
    268                         tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
    269                         return tevent_req_post(req, ev);
    270                 }
    271                 state->fsp = fsp;
    272         }
    273279
    274280        switch (in_ctl_code) {
     
    379385                return req;
    380386
    381         case 0x00144064:        /* FSCTL_SRV_ENUMERATE_SNAPSHOTS */
    382         {
    383                 /*
    384                  * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
    385                  * and return their volume names.  If max_data_count is 16, then it is just
    386                  * asking for the number of volumes and length of the combined names.
    387                  *
    388                  * pdata is the data allocated by our caller, but that uses
    389                  * total_data_count (which is 0 in our case) rather than max_data_count.
    390                  * Allocate the correct amount and return the pointer to let
    391                  * it be deallocated when we return.
    392                  */
    393                 struct shadow_copy_data *shadow_data = NULL;
    394                 bool labels = False;
    395                 uint32_t labels_data_count = 0;
    396                 uint32_t data_count;
    397                 uint32_t i;
    398                 char *pdata;
     387        default: {
     388                uint8_t *out_data = NULL;
     389                uint32_t out_data_len = 0;
    399390                NTSTATUS status;
    400391
     
    404395                }
    405396
    406                 if (in_max_output < 16) {
    407                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: "
    408                                  "in_max_output(%u) < 16 is invalid!\n",
    409                                  in_max_output));
    410                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    411                         return tevent_req_post(req, ev);
    412                 }
    413 
    414                 if (in_max_output > 16) {
    415                         labels = True;
    416                 }
    417 
    418                 shadow_data = TALLOC_ZERO_P(talloc_tos(),
    419                                             struct shadow_copy_data);
    420                 if (tevent_req_nomem(shadow_data, req)) {
    421                         DEBUG(0,("TALLOC_ZERO() failed!\n"));
    422                         return tevent_req_post(req, ev);
    423                 }
    424 
    425                 /*
    426                  * Call the VFS routine to actually do the work.
    427                  */
    428                 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)
    429                     != 0) {
    430                         if (errno == ENOSYS) {
    431                                 DEBUG(5, ("FSCTL_GET_SHADOW_COPY_DATA: "
    432                                           "connectpath %s, not supported.\n",
    433                                           smbreq->conn->connectpath));
    434                                 status = NT_STATUS_NOT_SUPPORTED;
     397                status = smb_fsctl(fsp,
     398                                       state,
     399                                       in_ctl_code,
     400                                       smbreq->flags2,
     401                                       in_input.data,
     402                                       in_input.length,
     403                                       &out_data,
     404                                       in_max_output,
     405                                       &out_data_len);
     406                state->out_output = data_blob_const(out_data, out_data_len);
     407                if (NT_STATUS_IS_OK(status)) {
     408                        tevent_req_done(req);
     409                        return tevent_req_post(req, ev);
     410                }
     411
     412                if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
     413                        if (IS_IPC(smbreq->conn)) {
     414                                status = NT_STATUS_FS_DRIVER_REQUIRED;
    435415                        } else {
    436                                 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: "
    437                                          "connectpath %s, failed.\n",
    438                                          smbreq->conn->connectpath));
    439                                 status = map_nt_error_from_unix(errno);
     416                                status = NT_STATUS_INVALID_DEVICE_REQUEST;
    440417                        }
    441                         TALLOC_FREE(shadow_data);
    442                         tevent_req_nterror(req, status);
    443                         return tevent_req_post(req, ev);
    444                 }
    445 
    446                 labels_data_count =
    447                         (shadow_data->num_volumes*2*sizeof(SHADOW_COPY_LABEL))
    448                         + 2;
    449 
    450                 if (labels) {
    451                         data_count = 12+labels_data_count+4;
    452                 } else {
    453                         data_count = 16;
    454                 }
    455 
    456                 if (labels && (in_max_output < data_count)) {
    457                         DEBUG(0, ("FSCTL_GET_SHADOW_COPY_DATA: "
    458                                   "in_max_output(%u) too small (%u) bytes "
    459                                   "needed!\n", in_max_output, data_count));
    460                         TALLOC_FREE(shadow_data);
    461                         tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
    462                         return tevent_req_post(req, ev);
    463                 }
    464 
    465                 state->out_output = data_blob_talloc(state, NULL, data_count);
    466                 if (tevent_req_nomem(state->out_output.data, req)) {
    467                         return tevent_req_post(req, ev);
    468                 }
    469 
    470                 pdata = (char *)state->out_output.data;
    471 
    472                 /* num_volumes 4 bytes */
    473                 SIVAL(pdata, 0, shadow_data->num_volumes);
    474 
    475                 if (labels) {
    476                         /* num_labels 4 bytes */
    477                         SIVAL(pdata, 4, shadow_data->num_volumes);
    478                 }
    479 
    480                 /* needed_data_count 4 bytes */
    481                 SIVAL(pdata, 8, labels_data_count+4);
    482 
    483                 pdata += 12;
    484 
    485                 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for "
    486                           "path[%s].\n",
    487                           shadow_data->num_volumes, fsp_str_dbg(fsp)));
    488                 if (labels && shadow_data->labels) {
    489                         for (i=0; i<shadow_data->num_volumes; i++) {
    490                                 srvstr_push(pdata, smbreq->flags2,
    491                                             pdata, shadow_data->labels[i],
    492                                             2*sizeof(SHADOW_COPY_LABEL),
    493                                             STR_UNICODE|STR_TERMINATE);
    494                                 pdata += 2*sizeof(SHADOW_COPY_LABEL);
    495                                 DEBUGADD(10, ("Label[%u]: '%s'\n", i,
    496                                               shadow_data->labels[i]));
    497                         }
    498                 }
    499 
    500                 TALLOC_FREE(shadow_data);
    501 
    502                 tevent_req_done(req);
     418                }
     419
     420                tevent_req_nterror(req, status);
    503421                return tevent_req_post(req, ev);
    504         }
    505 
    506         default:
    507                 if (IS_IPC(smbreq->conn)) {
    508                         tevent_req_nterror(req, NT_STATUS_FS_DRIVER_REQUIRED);
    509                         return tevent_req_post(req, ev);
    510                 }
    511                 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
    512                 return tevent_req_post(req, ev);
     422        }
    513423        }
    514424
Note: See TracChangeset for help on using the changeset viewer.