cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

rdpdr-fs-messages-file-info.c (11545B)


      1/*
      2 * Licensed to the Apache Software Foundation (ASF) under one
      3 * or more contributor license agreements.  See the NOTICE file
      4 * distributed with this work for additional information
      5 * regarding copyright ownership.  The ASF licenses this file
      6 * to you under the Apache License, Version 2.0 (the
      7 * "License"); you may not use this file except in compliance
      8 * with the License.  You may obtain a copy of the License at
      9 *
     10 *   http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing,
     13 * software distributed under the License is distributed on an
     14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     15 * KIND, either express or implied.  See the License for the
     16 * specific language governing permissions and limitations
     17 * under the License.
     18 */
     19
     20#include "channels/rdpdr/rdpdr-fs-messages-file-info.h"
     21#include "channels/rdpdr/rdpdr.h"
     22#include "download.h"
     23#include "fs.h"
     24#include "unicode.h"
     25
     26#include <guacamole/client.h>
     27#include <winpr/file.h>
     28#include <winpr/nt.h>
     29#include <winpr/stream.h>
     30#include <winpr/wtypes.h>
     31
     32#include <stdint.h>
     33#include <string.h>
     34
     35void guac_rdpdr_fs_process_query_basic_info(guac_rdp_common_svc* svc,
     36        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
     37        wStream* input_stream) {
     38
     39    wStream* output_stream;
     40    guac_rdp_fs_file* file;
     41
     42    /* Get file */
     43    file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
     44    if (file == NULL)
     45        return;
     46
     47    guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
     48            iorequest->file_id);
     49
     50    output_stream = guac_rdpdr_new_io_completion(device,
     51            iorequest->completion_id, STATUS_SUCCESS, 40);
     52
     53    Stream_Write_UINT32(output_stream, 36);
     54    Stream_Write_UINT64(output_stream, file->ctime);      /* CreationTime   */
     55    Stream_Write_UINT64(output_stream, file->atime);      /* LastAccessTime */
     56    Stream_Write_UINT64(output_stream, file->mtime);      /* LastWriteTime  */
     57    Stream_Write_UINT64(output_stream, file->mtime);      /* ChangeTime     */
     58    Stream_Write_UINT32(output_stream, file->attributes); /* FileAttributes */
     59
     60    /* Reserved field must not be sent */
     61
     62    guac_rdp_common_svc_write(svc, output_stream);
     63
     64}
     65
     66void guac_rdpdr_fs_process_query_standard_info(guac_rdp_common_svc* svc,
     67        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
     68        wStream* input_stream) {
     69
     70    wStream* output_stream;
     71    guac_rdp_fs_file* file;
     72    BOOL is_directory = FALSE;
     73
     74    /* Get file */
     75    file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
     76    if (file == NULL)
     77        return;
     78
     79    guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
     80            iorequest->file_id);
     81
     82    if (file->attributes & FILE_ATTRIBUTE_DIRECTORY)
     83        is_directory = TRUE;
     84
     85    output_stream = guac_rdpdr_new_io_completion(device,
     86            iorequest->completion_id, STATUS_SUCCESS, 26);
     87
     88    Stream_Write_UINT32(output_stream, 22);
     89    Stream_Write_UINT64(output_stream, file->size);   /* AllocationSize */
     90    Stream_Write_UINT64(output_stream, file->size);   /* EndOfFile      */
     91    Stream_Write_UINT32(output_stream, 1);            /* NumberOfLinks  */
     92    Stream_Write_UINT8(output_stream,  0);            /* DeletePending  */
     93    Stream_Write_UINT8(output_stream,  is_directory); /* Directory      */
     94
     95    /* Reserved field must not be sent */
     96
     97    guac_rdp_common_svc_write(svc, output_stream);
     98
     99}
    100
    101void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdp_common_svc* svc,
    102        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    103        wStream* input_stream) {
    104
    105    wStream* output_stream;
    106    guac_rdp_fs_file* file;
    107
    108    /* Get file */
    109    file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
    110    if (file == NULL)
    111        return;
    112
    113    guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
    114            iorequest->file_id);
    115
    116    output_stream = guac_rdpdr_new_io_completion(device,
    117            iorequest->completion_id, STATUS_SUCCESS, 12);
    118
    119    Stream_Write_UINT32(output_stream, 8);
    120    Stream_Write_UINT32(output_stream, file->attributes); /* FileAttributes */
    121    Stream_Write_UINT32(output_stream, 0);                /* ReparseTag */
    122
    123    /* Reserved field must not be sent */
    124
    125    guac_rdp_common_svc_write(svc, output_stream);
    126
    127}
    128
    129void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc,
    130        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    131        int length, wStream* input_stream) {
    132
    133    int result;
    134    int filename_length;
    135    wStream* output_stream;
    136    char destination_path[GUAC_RDP_FS_MAX_PATH];
    137
    138    /* Check stream size prior to reading. */
    139    if (Stream_GetRemainingLength(input_stream) < 6) {
    140        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set "
    141                "Information Request (FileRenameInformation) PDU does not "
    142                "contain the expected number of bytes.  File redirection "
    143                "may not work as expected.");
    144        return;
    145    }
    146        
    147    /* Read structure */
    148    Stream_Seek_UINT8(input_stream); /* ReplaceIfExists */
    149    Stream_Seek_UINT8(input_stream); /* RootDirectory */
    150    Stream_Read_UINT32(input_stream, filename_length); /* FileNameLength */
    151
    152    if (Stream_GetRemainingLength(input_stream) < filename_length) {
    153        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set "
    154                "Information Request (FileRenameInformation) PDU does not "
    155                "contain the expected number of bytes.  File redirection "
    156                "may not work as expected.");
    157        return;
    158    }
    159    
    160    /* Convert name to UTF-8 */
    161    guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), filename_length/2,
    162            destination_path, sizeof(destination_path));
    163
    164    guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]"
    165            "destination_path=\"%s\"", __func__, iorequest->file_id,
    166            destination_path);
    167
    168    /* If file moving to \Download folder, start stream, do not move */
    169    if (strncmp(destination_path, "\\Download\\", 10) == 0
    170			&& !((guac_rdp_fs*) device->data)->disable_download) {
    171
    172        guac_rdp_fs_file* file;
    173
    174        /* Get file */
    175        file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id);
    176        if (file == NULL)
    177            return;
    178
    179        /* Initiate download, pretend move succeeded */
    180        guac_client_for_owner(svc->client, guac_rdp_download_to_user, file->absolute_path);
    181        output_stream = guac_rdpdr_new_io_completion(device,
    182                iorequest->completion_id, STATUS_SUCCESS, 4);
    183
    184    }
    185
    186    /* Otherwise, rename as requested */
    187    else {
    188
    189        result = guac_rdp_fs_rename((guac_rdp_fs*) device->data,
    190                iorequest->file_id, destination_path);
    191        if (result < 0)
    192            output_stream = guac_rdpdr_new_io_completion(device,
    193                    iorequest->completion_id, guac_rdp_fs_get_status(result), 4);
    194        else
    195            output_stream = guac_rdpdr_new_io_completion(device,
    196                    iorequest->completion_id, STATUS_SUCCESS, 4);
    197
    198    }
    199
    200    Stream_Write_UINT32(output_stream, length);
    201    guac_rdp_common_svc_write(svc, output_stream);
    202
    203}
    204
    205void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc,
    206        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    207        int length, wStream* input_stream) {
    208
    209    int result;
    210    UINT64 size;
    211    wStream* output_stream;
    212
    213    /* Check to make sure the stream has at least 8 bytes (UINT64) */
    214    if (Stream_GetRemainingLength(input_stream) < 8) {
    215        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set "
    216                "Information Request (FileAllocationInformation) PDU does not "
    217                "contain the expected number of bytes.  File redirection "
    218                "may not work as expected.");
    219        return;
    220    }
    221    
    222    /* Read new size */
    223    Stream_Read_UINT64(input_stream, size); /* AllocationSize */
    224
    225    guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] "
    226            "size=%" PRIu64, __func__, iorequest->file_id, (uint64_t) size);
    227
    228    /* Truncate file */
    229    result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, iorequest->file_id, size);
    230    if (result < 0)
    231        output_stream = guac_rdpdr_new_io_completion(device,
    232                iorequest->completion_id, guac_rdp_fs_get_status(result), 4);
    233    else
    234        output_stream = guac_rdpdr_new_io_completion(device,
    235                iorequest->completion_id, STATUS_SUCCESS, 4);
    236
    237    Stream_Write_UINT32(output_stream, length);
    238    guac_rdp_common_svc_write(svc, output_stream);
    239
    240}
    241
    242void guac_rdpdr_fs_process_set_disposition_info(guac_rdp_common_svc* svc,
    243        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    244        int length, wStream* input_stream) {
    245
    246    wStream* output_stream;
    247
    248    /* Delete file */
    249    int result = guac_rdp_fs_delete((guac_rdp_fs*) device->data, iorequest->file_id);
    250    if (result < 0)
    251        output_stream = guac_rdpdr_new_io_completion(device,
    252                iorequest->completion_id, guac_rdp_fs_get_status(result), 4);
    253    else
    254        output_stream = guac_rdpdr_new_io_completion(device,
    255                iorequest->completion_id, STATUS_SUCCESS, 4);
    256
    257    guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__,
    258            iorequest->file_id);
    259
    260    Stream_Write_UINT32(output_stream, length);
    261
    262    guac_rdp_common_svc_write(svc, output_stream);
    263
    264}
    265
    266void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc,
    267        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    268        int length, wStream* input_stream) {
    269
    270    int result;
    271    UINT64 size;
    272    wStream* output_stream;
    273
    274    /* Check to make sure stream contains at least 8 bytes (UINT64) */
    275    if (Stream_GetRemainingLength(input_stream) < 8) {
    276        guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set "
    277                "Information Request (FileEndOfFileInformation) PDU does not "
    278                "contain the expected number of bytes.  File redirection "
    279                "may not work as expected.");
    280        return;
    281    }
    282    
    283    /* Read new size */
    284    Stream_Read_UINT64(input_stream, size); /* AllocationSize */
    285
    286    guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] "
    287            "size=%" PRIu64, __func__, iorequest->file_id, (uint64_t) size);
    288
    289    /* Truncate file */
    290    result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, iorequest->file_id, size);
    291    if (result < 0)
    292        output_stream = guac_rdpdr_new_io_completion(device,
    293                iorequest->completion_id, guac_rdp_fs_get_status(result), 4);
    294    else
    295        output_stream = guac_rdpdr_new_io_completion(device,
    296                iorequest->completion_id, STATUS_SUCCESS, 4);
    297
    298    Stream_Write_UINT32(output_stream, length);
    299    guac_rdp_common_svc_write(svc, output_stream);
    300
    301}
    302
    303void guac_rdpdr_fs_process_set_basic_info(guac_rdp_common_svc* svc,
    304        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
    305        int length, wStream* input_stream) {
    306
    307    wStream* output_stream = guac_rdpdr_new_io_completion(device,
    308            iorequest->completion_id, STATUS_SUCCESS, 4);
    309
    310    /* Currently do nothing, just respond */
    311    Stream_Write_UINT32(output_stream, length);
    312
    313    guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] IGNORED",
    314            __func__, iorequest->file_id);
    315
    316    guac_rdp_common_svc_write(svc, output_stream);
    317
    318}
    319