Changeset 751 for trunk/server/source3/smbd/smb2_ioctl.c
- Timestamp:
- Nov 29, 2012, 1:59:04 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server/source3/smbd/smb2_ioctl.c
r745 r751 30 30 struct tevent_context *ev, 31 31 struct smbd_smb2_request *smb2req, 32 struct files_struct *in_fsp, 32 33 uint32_t in_ctl_code, 33 uint64_t in_file_id_volatile,34 34 DATA_BLOB in_input, 35 35 uint32_t in_max_output, … … 42 42 NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req) 43 43 { 44 const uint8_t *inhdr;44 NTSTATUS status; 45 45 const uint8_t *inbody; 46 46 int i = req->current_idx; 47 size_t expected_body_size = 0x39;48 size_t body_size;49 47 uint32_t in_ctl_code; 50 48 uint64_t in_file_id_persistent; 51 49 uint64_t in_file_id_volatile; 50 struct files_struct *in_fsp = NULL; 52 51 uint32_t in_input_offset; 53 52 uint32_t in_input_length; … … 57 56 struct tevent_req *subreq; 58 57 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 } 64 62 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 }70 63 71 64 in_ctl_code = IVAL(inbody, 0x04); … … 77 70 in_flags = IVAL(inbody, 0x30); 78 71 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))) { 80 82 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); 81 83 } … … 88 90 in_input_buffer.length = in_input_length; 89 91 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; 97 120 } 98 121 99 122 subreq = smbd_smb2_ioctl_send(req, 100 123 req->sconn->smb2.event_ctx, 101 req, 124 req, in_fsp, 102 125 in_ctl_code, 103 in_file_id_volatile,104 126 in_input_buffer, 105 127 in_max_output_length, … … 222 244 struct tevent_context *ev, 223 245 struct smbd_smb2_request *smb2req, 246 struct files_struct *fsp, 224 247 uint32_t in_ctl_code, 225 uint64_t in_file_id_volatile,226 248 DATA_BLOB in_input, 227 249 uint32_t in_max_output, … … 231 253 struct smbd_smb2_ioctl_state *state; 232 254 struct smb_request *smbreq; 233 files_struct *fsp = NULL;234 255 struct tevent_req *subreq; 235 256 … … 241 262 state->smb2req = smb2req; 242 263 state->smbreq = NULL; 243 state->fsp = NULL;264 state->fsp = fsp; 244 265 state->in_input = in_input; 245 266 state->in_max_output = in_max_output; 246 267 state->out_output = data_blob_null; 247 268 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)); 250 273 251 274 smbreq = smbd_smb2_fake_smb_request(smb2req); … … 254 277 } 255 278 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 }273 279 274 280 switch (in_ctl_code) { … … 379 385 return req; 380 386 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; 399 390 NTSTATUS status; 400 391 … … 404 395 } 405 396 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; 435 415 } 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; 440 417 } 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); 503 421 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 } 513 423 } 514 424
Note:
See TracChangeset
for help on using the changeset viewer.