Esempio n. 1
0
void devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus)
{
    struct stream *s;
    int            bytes;

    if (IoStatus != NT_STATUS_SUCCESS)
    {
        FUSE_DATA *fuse_data = dev_redir_fuse_data_dequeue(irp);
        if (fuse_data)
        {
            xfuse_devredir_cb_rmdir_or_file(fuse_data->data_ptr, IoStatus);
            free(fuse_data);
        }
        devredir_irp_delete(irp);
        return;
    }

    xstream_new(s, 1024);

    irp->completion_type = CID_RMDIR_OR_FILE_RESP;
    devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
                                    irp->CompletionId,
                                    IRP_MJ_SET_INFORMATION, 0);

    xstream_wr_u32_le(s, FileDispositionInformation);
    xstream_wr_u32_le(s, 0); /* length is zero */
    xstream_seek(s, 24);     /* padding        */

    /* send to client */
    bytes = xstream_len(s);
    send_channel_data(g_rdpdr_chan_id, s->data, bytes);
    xstream_free(s);

    return;
}
Esempio n. 2
0
int dev_redir_send_drive_close_request(tui16 Component, tui16 PacketId,
                                       tui32 DeviceId,
                                       tui32 FileId,
                                       tui32 CompletionId,
                                       tui32 MajorFunction,
                                       tui32 MinorFunc,
                                       int pad_len)
{
    struct stream *s;
    int            bytes;

    xstream_new(s, 1024);

    devredir_insert_DeviceIoRequest(s, DeviceId, FileId, CompletionId,
                                    MajorFunction, MinorFunc);

    if (pad_len)
        xstream_seek(s, pad_len);

    /* send to client */
    bytes = xstream_len(s);
    send_channel_data(g_rdpdr_chan_id, s->data, bytes);

    xstream_free(s);
    log_debug("sent close request; expect CID_FILE_CLOSE");
    return 0;
}
Esempio n. 3
0
int APP_CC
dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId,
                     const char *buf, int Length, tui64 Offset)
{
    struct stream *s;
    IRP           *irp;
    IRP           *new_irp;
    int            bytes;

    log_debug("DeviceId=%d FileId=%d Length=%d Offset=%lld",
              DeviceId, FileId, Length, Offset);

    xstream_new(s, 1024 + Length);

    if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL)
    {
        log_error("no IRP found with FileId = %d", FileId);
        xfuse_devredir_cb_write_file(fusep, NULL, 0);
        xstream_free(s);
        return -1;
    }

    /* create a new IRP for this request */
    if ((new_irp = devredir_irp_clone(irp)) == NULL)
    {
        /* system out of memory */
        xfuse_devredir_cb_write_file(fusep, NULL, 0);
        xstream_free(s);
        return -1;
    }
    new_irp->FileId = 0;
    new_irp->completion_type = CID_WRITE;
    new_irp->CompletionId = g_completion_id++;
    devredir_fuse_data_enqueue(new_irp, fusep);

    devredir_insert_DeviceIoRequest(s,
                                    DeviceId,
                                    FileId,
                                    new_irp->CompletionId,
                                    IRP_MJ_WRITE,
                                    0);

    xstream_wr_u32_le(s, Length);
    xstream_wr_u64_le(s, Offset);
    xstream_seek(s, 20); /* padding */

    /* now insert real data */
    xstream_copyin(s, buf, Length);

    /* send to client */
    bytes = xstream_len(s);
    send_channel_data(g_rdpdr_chan_id, s->data, bytes);
    xstream_free(s);

    return 0;
}
Esempio n. 4
0
/**
 * @brief process client's response to our core_capability_req() msg
 *
 * @param   s   stream containing client's response
 *****************************************************************************/
void dev_redir_proc_client_core_cap_resp(struct stream *s)
{
    int i;
    tui16 num_caps;
    tui16 cap_type;
    tui16 cap_len;
    tui32 cap_version;
    char* holdp;

    xstream_rd_u16_le(s, num_caps);
    xstream_seek(s, 2);  /* padding */

    for (i = 0; i < num_caps; i++)
    {
        holdp = s->p;
        xstream_rd_u16_le(s, cap_type);
        xstream_rd_u16_le(s, cap_len);
        xstream_rd_u32_le(s, cap_version);

        switch (cap_type)
        {
            case CAP_GENERAL_TYPE:
                log_debug("got CAP_GENERAL_TYPE");
                break;

            case CAP_PRINTER_TYPE:
                log_debug("got CAP_PRINTER_TYPE");
                g_is_printer_redir_supported = 1;
                break;

            case CAP_PORT_TYPE:
                log_debug("got CAP_PORT_TYPE");
                g_is_port_redir_supported = 1;
                break;

            case CAP_DRIVE_TYPE:
                log_debug("got CAP_DRIVE_TYPE");
                g_is_drive_redir_supported = 1;
                if (cap_version == 2)
                {
                    g_drive_redir_version = 2;
                }
                break;

            case CAP_SMARTCARD_TYPE:
                log_debug("got CAP_SMARTCARD_TYPE");
                g_is_smartcard_redir_supported = 1;
                scard_init();
                break;
        }
        s->p = holdp + cap_len;
    }
}
Esempio n. 5
0
int APP_CC
devredir_file_read(void *fusep, tui32 DeviceId, tui32 FileId,
                   tui32 Length, tui64 Offset)
{
    struct stream *s;
    IRP           *irp;
    IRP           *new_irp;
    int            bytes;

    xstream_new(s, 1024);

    if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL)
    {
        log_error("no IRP found with FileId = %d", FileId);
        xfuse_devredir_cb_read_file(fusep, NULL, 0);
        xstream_free(s);
        return -1;
    }

    /* create a new IRP for this request */
    if ((new_irp = devredir_irp_clone(irp)) == NULL)
    {
        /* system out of memory */
        xfuse_devredir_cb_read_file(fusep, NULL, 0);
        xstream_free(s);
        return -1;
    }
    new_irp->FileId = 0;
    new_irp->completion_type = CID_READ;
    new_irp->CompletionId = g_completion_id++;
    devredir_fuse_data_enqueue(new_irp, fusep);

    devredir_insert_DeviceIoRequest(s,
                                    DeviceId,
                                    FileId,
                                    new_irp->CompletionId,
                                    IRP_MJ_READ,
                                    0);

    xstream_wr_u32_le(s, Length);
    xstream_wr_u64_le(s, Offset);
    xstream_seek(s, 20);

    /* send to client */
    bytes = xstream_len(s);
    send_channel_data(g_rdpdr_chan_id, s->data, bytes);
    xstream_free(s);

    return 0;
}
Esempio n. 6
0
static struct stream * APP_CC
scard_make_new_ioctl(IRP *irp, tui32 ioctl)
{
    /*
     * format of device control request
     *
     * DeviceIoRequest
     * u16       RDPDR_CTYP_CORE
     * u16       PAKID_CORE_DEVICE_IOREQUEST
     * u32       DeviceId
     * u32       FileId
     * u32       CompletionId
     * u32       MajorFunction
     * u32       MinorFunction
     *
     * u32       OutputBufferLength SHOULD be 2048
     * u32       InputBufferLength
     * u32       IoControlCode
     * 20 bytes  padding
     * xx bytes  InputBuffer (variable)
     */

    struct stream *s;

    xstream_new(s, 1024 * 3);
    if (s == NULL)
    {
        log_error("system out of memory");
        return s;
    }

    devredir_insert_DeviceIoRequest(s,
                                    irp->DeviceId,
                                    irp->FileId,
                                    irp->CompletionId,
                                    IRP_MJ_DEVICE_CONTROL,
                                    0);

    xstream_wr_u32_le(s, 2048);        /* OutputBufferLength               */
    xstream_wr_u32_le(s, 0);           /* InputBufferLength - insert later */
    xstream_wr_u32_le(s, ioctl);       /* Ioctl Code                       */
    xstream_seek(s, 20);               /* padding                          */

    /* [MS-RPCE] 2.2.6.1 */
    xstream_wr_u32_le(s, 0x00081001);  /* len 8, LE, v1                    */
    xstream_wr_u32_le(s, 0xcccccccc);  /* filler                           */

    return s;
}
Esempio n. 7
0
/**
 * @brief process client's repsonse to our core_capability_req() msg
 *
 * @param   s   stream containing client's response
 *****************************************************************************/
void dev_redir_proc_client_core_cap_resp(struct stream *s)
{
    int i;
    tui16 num_caps;
    tui16 cap_type;
    tui16 cap_len;
    tui32 cap_version;

    xstream_rd_u16_le(s, num_caps);
    xstream_seek(s, 2);  /* padding */

    for (i = 0; i < num_caps; i++)
    {
        xstream_rd_u16_le(s, cap_type);
        xstream_rd_u16_le(s, cap_len);
        xstream_rd_u32_le(s, cap_version);

        /* remove header length and version */
        cap_len -= 8;

        switch (cap_type)
        {
            case CAP_GENERAL_TYPE:
                log_debug("got CAP_GENERAL_TYPE");
                xstream_seek(s, cap_len);
                break;

            case CAP_PRINTER_TYPE:
                log_debug("got CAP_PRINTER_TYPE");
                g_is_printer_redir_supported = 1;
                xstream_seek(s, cap_len);
                break;

            case CAP_PORT_TYPE:
                log_debug("got CAP_PORT_TYPE");
                g_is_port_redir_supported = 1;
                xstream_seek(s, cap_len);
                break;

            case CAP_DRIVE_TYPE:
                log_debug("got CAP_DRIVE_TYPE");
                g_is_drive_redir_supported = 1;
                if (cap_version == 2)
                    g_drive_redir_version = 2;
                xstream_seek(s, cap_len);
                break;

            case CAP_SMARTCARD_TYPE:
                log_debug("got CAP_SMARTCARD_TYPE");
                g_is_smartcard_redir_supported = 1;
                xstream_seek(s, cap_len);
                break;
        }
    }
}
Esempio n. 8
0
int dev_redir_send_drive_create_request(tui32 device_id,
                                        const char *path,
                                        tui32 DesiredAccess,
                                        tui32 CreateOptions,
                                        tui32 CreateDisposition,
                                        tui32 completion_id)
{
    struct stream *s;
    int            bytes;
    int            len;

    log_debug("DesiredAccess=0x%x CreateDisposition=0x%x CreateOptions=0x%x",
              DesiredAccess, CreateDisposition, CreateOptions);

    /* path in unicode needs this much space */
    len = ((g_mbstowcs(NULL, path, 0) * sizeof(twchar)) / 2) + 2;

    xstream_new(s, 1024 + len);

    devredir_insert_DeviceIoRequest(s,
                                    device_id,
                                    0,
                                    completion_id,
                                    IRP_MJ_CREATE,
                                    0);

    xstream_wr_u32_le(s, DesiredAccess);     /* DesiredAccess              */
    xstream_wr_u32_le(s, 0);                 /* AllocationSize high unused */
    xstream_wr_u32_le(s, 0);                 /* AllocationSize low  unused */
    xstream_wr_u32_le(s, 0);                 /* FileAttributes             */
    xstream_wr_u32_le(s, 3);                 /* SharedAccess LK_TODO       */
    xstream_wr_u32_le(s, CreateDisposition); /* CreateDisposition          */
    xstream_wr_u32_le(s, CreateOptions);     /* CreateOptions              */
    xstream_wr_u32_le(s, len);               /* PathLength                 */
    devredir_cvt_to_unicode(s->p, path);     /* path in unicode            */
    xstream_seek(s, len);

    /* send to client */
    bytes = xstream_len(s);
    send_channel_data(g_rdpdr_chan_id, s->data, bytes);

    xstream_free(s);
    return 0;
}
Esempio n. 9
0
void dev_redir_proc_query_dir_response(IRP *irp,
                                       struct stream *s_in,
                                       tui32 DeviceId,
                                       tui32 CompletionId,
                                       tui32 IoStatus)
{
    FUSE_DATA  *fuse_data = NULL;
    XRDP_INODE *xinode    = NULL;

    tui32 Length;
    tui32 NextEntryOffset;
    tui64 CreationTime;
    tui64 LastAccessTime;
    tui64 LastWriteTime;
    tui64 ChangeTime;
    tui64 EndOfFile;
    tui32 FileAttributes;
    tui32 FileNameLength;
    tui32 status;

#ifdef USE_SHORT_NAMES_IN_DIR_LISTING
    tui32 EaSize;
    tui8  ShortNameLength;
    tui8  Reserved;
#endif

    char  filename[256];
    int   i = 0;

    xstream_rd_u32_le(s_in, Length);

    if ((IoStatus == NT_STATUS_UNSUCCESSFUL) ||
        (IoStatus == STATUS_NO_MORE_FILES))
    {
        status = (IoStatus == STATUS_NO_MORE_FILES) ? 0 : IoStatus;
        fuse_data = dev_redir_fuse_data_dequeue(irp);
        xfuse_devredir_cb_enum_dir_done(fuse_data->data_ptr, status);
        irp->completion_type = CID_CLOSE;
        dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
                                           PAKID_CORE_DEVICE_IOREQUEST,
                                           DeviceId,
                                           irp->FileId,
                                           irp->CompletionId,
                                           IRP_MJ_CLOSE, 0, 32);
        free(fuse_data);
        return;
    }

    /* TODO check status for errors */

    /* process FILE_DIRECTORY_INFORMATION structures */
    while (i < Length)
    {
        log_debug("processing FILE_DIRECTORY_INFORMATION structs");

        xstream_rd_u32_le(s_in, NextEntryOffset);
        xstream_seek(s_in, 4);  /* FileIndex */
        xstream_rd_u64_le(s_in, CreationTime);
        xstream_rd_u64_le(s_in, LastAccessTime);
        xstream_rd_u64_le(s_in, LastWriteTime);
        xstream_rd_u64_le(s_in, ChangeTime);
        xstream_rd_u64_le(s_in, EndOfFile);
        xstream_seek(s_in, 8);  /* AllocationSize */
        xstream_rd_u32_le(s_in, FileAttributes);
        xstream_rd_u32_le(s_in, FileNameLength);

#ifdef USE_SHORT_NAMES_IN_DIR_LISTING
        xstream_rd_u32_le(s_in, EaSize);
        xstream_rd_u8(s_in, ShortNameLength);
        xstream_rd_u8(s_in, Reserved);
        xstream_seek(s_in, 23);  /* ShortName in Unicode */
#endif
        devredir_cvt_from_unicode_len(filename, s_in->p, FileNameLength);

#ifdef USE_SHORT_NAMES_IN_DIR_LISTING
        i += 70 + 23 + FileNameLength;
#else
        i += 64 + FileNameLength;
#endif
        //log_debug("NextEntryOffset:   0x%x", NextEntryOffset);
        //log_debug("CreationTime:      0x%llx", CreationTime);
        //log_debug("LastAccessTime:    0x%llx", LastAccessTime);
        //log_debug("LastWriteTime:     0x%llx", LastWriteTime);
        //log_debug("ChangeTime:        0x%llx", ChangeTime);
        //log_debug("EndOfFile:         %lld", EndOfFile);
        //log_debug("FileAttributes:    0x%x", FileAttributes);
#ifdef USE_SHORT_NAMES_IN_DIR_LISTING
        //log_debug("ShortNameLength:   %d", ShortNameLength);
#endif
        //log_debug("FileNameLength:    %d", FileNameLength);
        log_debug("FileName:          %s", filename);

        if ((xinode = calloc(1, sizeof(struct xrdp_inode))) == NULL)
        {
            log_error("system out of memory");
            fuse_data = dev_redir_fuse_data_peek(irp);
            xfuse_devredir_cb_enum_dir(fuse_data->data_ptr, NULL);
            return;
        }

        strcpy(xinode->name, filename);
        xinode->size = (size_t) EndOfFile;
        xinode->mode = WINDOWS_TO_LINUX_FILE_PERM(FileAttributes);
        xinode->atime = WINDOWS_TO_LINUX_TIME(LastAccessTime);
        xinode->mtime = WINDOWS_TO_LINUX_TIME(LastWriteTime);
        xinode->ctime = WINDOWS_TO_LINUX_TIME(CreationTime);

        /* add this entry to xrdp file system */
        fuse_data = dev_redir_fuse_data_peek(irp);
        xfuse_devredir_cb_enum_dir(fuse_data->data_ptr, xinode);
    }

    dev_redir_send_drive_dir_request(irp, DeviceId, 0, NULL);
}
Esempio n. 10
0
int APP_CC
dev_redir_data_in(struct stream *s, int chan_id, int chan_flags, int length,
                  int total_length)
{
    struct stream *ls;
    tui16          comp_type;
    tui16          pktID;
    tui16          minor_ver;
    int            rv = 0;

    /*
     * handle packet fragmentation
     */
    if ((chan_flags & 3) == 3)
    {
        /* all data contained in one packet */
        ls = s;
    }
    else
    {
        /* is this is the first packet? */
        if (chan_flags & 1)
            xstream_new(g_input_stream, total_length);

        xstream_copyin(g_input_stream, s->p, length);

        /* in last packet, chan_flags & 0x02 will be true */
        if ((chan_flags & 2) == 0)
            return 0;

        g_input_stream->p = g_input_stream->data;
        ls = g_input_stream;
    }

    /* read header from incoming data */
    xstream_rd_u16_le(ls, comp_type);
    xstream_rd_u16_le(ls, pktID);

    /* for now we only handle core type, not printers */
    if (comp_type != RDPDR_CTYP_CORE)
    {
        log_error("invalid component type in response; expected 0x%x got 0x%x",
                  RDPDR_CTYP_CORE, comp_type);

        rv = -1;
        goto done;
    }

    /* figure out what kind of response we have gotten */
    switch (pktID)
    {
        case PAKID_CORE_CLIENTID_CONFIRM:
            xstream_seek(ls, 2);  /* major version, we ignore it */
            xstream_rd_u16_le(ls, minor_ver);
            xstream_rd_u32_le(ls, g_clientID);

            g_client_rdp_version = minor_ver;

            switch (minor_ver)
            {
                case RDP_CLIENT_50:
                    break;

                case RDP_CLIENT_51:
                    break;

                case RDP_CLIENT_52:
                    break;

                case RDP_CLIENT_60_61:
                    break;
            }
            // LK_TODO dev_redir_send_server_clientID_confirm();
            break;

        case PAKID_CORE_CLIENT_NAME:
            /* client is telling us its computer name; do we even care? */

            /* let client know loggin was successful */
            dev_redir_send_server_user_logged_on();
            usleep(1000 * 100);

            /* let client know our capabilites */
            dev_redir_send_server_core_cap_req();

            /* send confirm clientID */
            dev_redir_send_server_clientID_confirm();
            break;

        case PAKID_CORE_CLIENT_CAPABILITY:
            dev_redir_proc_client_core_cap_resp(ls);
            break;

        case PAKID_CORE_DEVICELIST_ANNOUNCE:
            devredir_proc_client_devlist_announce_req(ls);
            break;

        case PAKID_CORE_DEVICE_IOCOMPLETION:
            dev_redir_proc_device_iocompletion(ls);
            break;

        default:
            log_error("got unknown response 0x%x", pktID);
            break;
    }

done:

    if (g_input_stream)
    {
        xstream_free(g_input_stream);
        g_input_stream = NULL;
    }

    return rv;
}
Esempio n. 11
0
static void APP_CC
scard_send_ListReaders(IRP *irp, int wide)
{
    /* see [MS-RDPESC] 2.2.2.4 */

    SMARTCARD     *sc;
    struct stream *s;
    int            bytes;
    tui32          ioctl;

    if ((sc = smartcards[irp->scard_index]) == NULL)
    {
        log_error("smartcards[%d] is NULL", irp->scard_index);
        return;
    }

    ioctl = (wide > 0) ? SCARD_IOCTL_LIST_READERS_W :
                         SCARD_IOCTL_LIST_READERS_A;

    if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL)
        return;

    xstream_wr_u32_le(s, 72); /* number of bytes to follow */
    xstream_seek(s, 0x1c);    /* freerdp does not use this */

    /* insert context */
    xstream_wr_u32_le(s, sc->Context_len);
    xstream_copyin(s, sc->Context, sc->Context_len);

    xstream_wr_u32_le(s, 36); /* length of mszGroups */
    xstream_wr_u16_le(s, 0x0053);
    xstream_wr_u16_le(s, 0x0043);
    xstream_wr_u16_le(s, 0x0061);
    xstream_wr_u16_le(s, 0x0072);
    xstream_wr_u16_le(s, 0x0064);
    xstream_wr_u16_le(s, 0x0024);
    xstream_wr_u16_le(s, 0x0041);
    xstream_wr_u16_le(s, 0x006c);
    xstream_wr_u16_le(s, 0x006c);
    xstream_wr_u16_le(s, 0x0052);
    xstream_wr_u16_le(s, 0x0065);
    xstream_wr_u16_le(s, 0x0061);
    xstream_wr_u16_le(s, 0x0064);
    xstream_wr_u16_le(s, 0x0065);
    xstream_wr_u16_le(s, 0x0072);
    xstream_wr_u16_le(s, 0x0073);

    xstream_wr_u32_le(s, 0x00);

    /* get stream len */
    bytes = xstream_len(s);

    /* InputBufferLength is number of bytes AFTER 20 byte padding  */
    *(s->data + 28) = bytes - 56;

    /* send to client */
    send_channel_data(g_rdpdr_chan_id, s->data, bytes);
    xstream_free(s);

    /*
    scard_device_control: dumping 120 bytes of data
    0000 00 08 00 00 58 00 00 00 2c 00 09 00 00 00 00 00 ....X...,.......
    0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    0020 01 10 08 00 cc cc cc cc 48 00 00 00 00 00 00 00 ........H.......
    0030 04 00 00 00 00 00 02 00 24 00 00 00 04 00 02 00 ........$.......
    0040 00 00 00 00 ff ff ff ff 04 00 00 00 84 db 03 01 ................
    0050 24 00 00 00 53 00 43 00 61 00 72 00 64 00 24 00 $...S.C.a.r.d.$.
    0060 41 00 6c 00 6c 00 52 00 65 00 61 00 64 00 65 00 A.l.l.R.e.a.d.e.
    0070 72 00 73 00 00 00 00 00                         r.s.....
    scard_device_control: output_len=2048 input_len=88 ioctl_code=0x9002c
    */

    /*
        scard_device_control: dumping 120 bytes of data
        0000 00 08 00 00 80 00 00 00 14 00 09 00 00 00 00 00 ................
        0010 2e 2e 00 00 00 00 00 00 02 00 00 00 00 00 00 00 ................
        0020 01 10 08 00 cc cc cc cc 48 00 00 00 00 00 00 00 ........H.......
        0030 02 00 00 00 00 00 00 00 72 64 00 00 00 00 00 00 ........rd......
        0040 81 27 00 00 00 00 00 00 04 00 00 00 84 b3 03 01 .'..............
        0050 24 00 00 00 53 00 43 00 61 00 72 00 64 00 24 00 $...S.C.a.r.d.$.
        0060 41 00 6c 00 6c 00 52 00 65 00 61 00 64 00 65 00 A.l.l.R.e.a.d.e.
        0070 72 00 73 00 00 00 00 00                         r.s.....
        scard_device_control: output_len=2048 input_len=128 ioctl_code=0x90014
    */
}