cscg24-guacamole

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

rdpdr.c (6196B)


      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.h"
     21#include "channels/rdpdr/rdpdr-fs.h"
     22#include "channels/rdpdr/rdpdr-messages.h"
     23#include "channels/rdpdr/rdpdr-printer.h"
     24#include "rdp.h"
     25#include "settings.h"
     26
     27#include <freerdp/channels/rdpdr.h>
     28#include <freerdp/freerdp.h>
     29#include <freerdp/settings.h>
     30#include <guacamole/client.h>
     31#include <guacamole/mem.h>
     32#include <winpr/stream.h>
     33
     34#include <stdlib.h>
     35
     36void guac_rdpdr_process_receive(guac_rdp_common_svc* svc,
     37        wStream* input_stream) {
     38
     39    int component;
     40    int packet_id;
     41
     42    /* 
     43     * Check that device redirection stream contains at least 4 bytes
     44     * (UINT16 + UINT16).
     45     */
     46    if (Stream_GetRemainingLength(input_stream) < 4) {
     47        guac_client_log(svc->client, GUAC_LOG_WARNING, "Device redirection "
     48                "channel PDU header does not contain the expected number of "
     49                "bytes. Device redirection may not function as expected.");
     50        return;
     51    }
     52    
     53    /* Read header */
     54    Stream_Read_UINT16(input_stream, component);
     55    Stream_Read_UINT16(input_stream, packet_id);
     56
     57    /* Core component */
     58    if (component == RDPDR_CTYP_CORE) {
     59
     60        /* Dispatch handlers based on packet ID */
     61        switch (packet_id) {
     62
     63            case PAKID_CORE_SERVER_ANNOUNCE:
     64                guac_rdpdr_process_server_announce(svc, input_stream);
     65                break;
     66
     67            case PAKID_CORE_CLIENTID_CONFIRM:
     68                guac_rdpdr_process_clientid_confirm(svc, input_stream);
     69                break;
     70
     71            case PAKID_CORE_DEVICE_REPLY:
     72                guac_rdpdr_process_device_reply(svc, input_stream);
     73                break;
     74
     75            case PAKID_CORE_DEVICE_IOREQUEST:
     76                guac_rdpdr_process_device_iorequest(svc, input_stream);
     77                break;
     78
     79            case PAKID_CORE_SERVER_CAPABILITY:
     80                guac_rdpdr_process_server_capability(svc, input_stream);
     81                break;
     82
     83            case PAKID_CORE_USER_LOGGEDON:
     84                guac_rdpdr_process_user_loggedon(svc, input_stream);
     85                break;
     86
     87            default:
     88                guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring "
     89                        "RDPDR core packet with unexpected ID: 0x%04x",
     90                        packet_id);
     91
     92        }
     93
     94    } /* end if core */
     95
     96    /* Printer component */
     97    else if (component == RDPDR_CTYP_PRN) {
     98
     99        /* Dispatch handlers based on packet ID */
    100        switch (packet_id) {
    101
    102            case PAKID_PRN_CACHE_DATA:
    103                guac_rdpdr_process_prn_cache_data(svc, input_stream);
    104                break;
    105
    106            case PAKID_PRN_USING_XPS:
    107                guac_rdpdr_process_prn_using_xps(svc, input_stream);
    108                break;
    109
    110            default:
    111                guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring RDPDR "
    112                        "printer packet with unexpected ID: 0x%04x",
    113                        packet_id);
    114
    115        }
    116
    117    } /* end if printer */
    118
    119    else
    120        guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring packet for "
    121                "unknown RDPDR component: 0x%04x", component);
    122
    123}
    124
    125wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device,
    126        int completion_id, int status, int size) {
    127
    128    wStream* output_stream = Stream_New(NULL, 16+size);
    129
    130    /* Write header */
    131    Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
    132    Stream_Write_UINT16(output_stream, PAKID_CORE_DEVICE_IOCOMPLETION);
    133
    134    /* Write content */
    135    Stream_Write_UINT32(output_stream, device->device_id);
    136    Stream_Write_UINT32(output_stream, completion_id);
    137    Stream_Write_UINT32(output_stream, status);
    138
    139    return output_stream;
    140
    141}
    142
    143void guac_rdpdr_process_connect(guac_rdp_common_svc* svc) {
    144
    145    /* Get data from client */
    146    guac_client* client = svc->client;
    147    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
    148
    149    guac_rdpdr* rdpdr = (guac_rdpdr*) guac_mem_zalloc(sizeof(guac_rdpdr));
    150    svc->data = rdpdr;
    151
    152    /* Register printer if enabled */
    153    if (rdp_client->settings->printing_enabled)
    154        guac_rdpdr_register_printer(svc, rdp_client->settings->printer_name);
    155
    156    /* Register drive if enabled */
    157    if (rdp_client->settings->drive_enabled)
    158        guac_rdpdr_register_fs(svc, rdp_client->settings->drive_name);
    159
    160}
    161
    162void guac_rdpdr_process_terminate(guac_rdp_common_svc* svc) {
    163
    164    guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
    165    if (rdpdr == NULL)
    166        return;
    167
    168    int i;
    169
    170    for (i=0; i<rdpdr->devices_registered; i++) {
    171        guac_rdpdr_device* device = &(rdpdr->devices[i]);
    172        guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unloading device %i "
    173                "(%s)", device->device_id, device->device_name);
    174        device->free_handler(svc, device);
    175    }
    176
    177    guac_mem_free(svc->data); /* rdpdr */
    178
    179}
    180
    181
    182void guac_rdpdr_load_plugin(rdpContext* context) {
    183
    184    guac_client* client = ((rdp_freerdp_context*) context)->client;
    185
    186    /* Load support for RDPDR */
    187    if (guac_rdp_common_svc_load_plugin(context, "rdpdr",
    188                CHANNEL_OPTION_COMPRESS_RDP, guac_rdpdr_process_connect,
    189                guac_rdpdr_process_receive, guac_rdpdr_process_terminate)) {
    190        guac_client_log(client, GUAC_LOG_WARNING, "Support for the RDPDR "
    191                "channel (device redirection) could not be loaded. Drive "
    192                "redirection and printing will not work. Sound MAY not work.");
    193    }
    194
    195}
    196