예제 #1
0
void APP_CC
scard_handle_EstablishContext_Return(struct stream *s, IRP *irp,
                                     tui32 DeviceId, tui32 CompletionId,
                                     tui32 IoStatus)
{
    tui32      len;
    int        tmp;
    SMARTCARD *sc;

    log_debug("entered");

    /* sanity check */
    if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
    {
        log_error("DeviceId/CompletionId do not match those in IRP");
        return;
    }

    if (IoStatus != 0)
    {
        log_error("failed to establish context - device not usable");
        /* LK_TODO delete irp and smartcard entry */
        return;
    }

    sc = smartcards[irp->scard_index];

    /* get OutputBufferLen */
    xstream_rd_u32_le(s, len);

    /* LK_TODO */
    g_hexdump(s->p, len);

    xstream_rd_u32_le(s, tmp); /* should be len 8, LE, V1 */
    xstream_rd_u32_le(s, tmp); /* marshalling flag        */
    xstream_rd_u32_le(s, tmp); /* ?? */
    xstream_rd_u32_le(s, tmp); /* ?? */
    xstream_rd_u32_le(s, tmp); /* ?? */
    xstream_rd_u32_le(s, tmp); /* ?? */
    xstream_rd_u32_le(s, tmp); /* ?? */
    xstream_rd_u32_le(s, len); /* len of context in bytes */
    sc->Context_len = len;
    xstream_copyout(sc->Context, s, len);

    if (LOG_LEVEL == LOG_DEBUG)
    {
        log_debug("dumping context (%d bytes)", sc->Context_len);
        g_hexdump(sc->Context, sc->Context_len);
    }

    irp->callback = scard_handle_ListReaders_Return;
    scard_send_ListReaders(irp, 1);

    /* LK_TODO need to delete IRP */
    log_debug("leaving");
}
예제 #2
0
void APP_CC
scard_handle_ListReaders_Return(struct stream *s, IRP *irp,
                                tui32 DeviceId, tui32 CompletionId,
                                tui32 IoStatus)
{
    tui32 len;

    log_debug("entered");

    /* sanity check */
    if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
    {
        log_error("DeviceId/CompletionId do not match those in IRP");
        return;
    }

    if (IoStatus != 0)
    {
        log_error("failed to list readers - device not usable");
        /* LK_TODO delete irp and smartcard entry */
        return;
    }

    /* get OutputBufferLen */
    xstream_rd_u32_le(s, len);

    /* LK_TODO */
    log_debug("dumping %d bytes", len);
    g_hexdump(s->p, len);

    log_debug("leaving");
}
예제 #3
0
파일: devredir.c 프로젝트: fishwgj/xrdp
/**
 * @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;
        }
    }
}
예제 #4
0
파일: devredir.c 프로젝트: speidy/xrdp
/**
 * @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;
    }
}
예제 #5
0
파일: devredir.c 프로젝트: fishwgj/xrdp
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);
}
예제 #6
0
파일: devredir.c 프로젝트: fishwgj/xrdp
void dev_redir_proc_device_iocompletion(struct stream *s)
{
    FUSE_DATA *fuse_data = NULL;
    IRP       *irp       = NULL;

    tui32      DeviceId;
    tui32      CompletionId;
    tui32      IoStatus;
    tui32      Length;

    xstream_rd_u32_le(s, DeviceId);
    xstream_rd_u32_le(s, CompletionId);
    xstream_rd_u32_le(s, IoStatus);

    /* LK_TODO need to check for IoStatus */

    log_debug("entered: IoStatus=0x%x CompletionId=%d", IoStatus, CompletionId);

    if ((irp = devredir_irp_find(CompletionId)) == NULL)
    {
        log_error("IRP with completion ID %d not found", CompletionId);
        return;
    }

    /* if callback has been set, call it */
    if (irp->callback)
    {
        (*irp->callback)(s, irp, DeviceId, CompletionId, IoStatus);
        goto done;
    }

    switch (irp->completion_type)
    {
    case CID_CREATE_DIR_REQ:
        log_debug("got CID_CREATE_DIR_REQ");
        if (IoStatus != NT_STATUS_SUCCESS)
        {
            /* we were trying to create a request to enumerate a dir */
            /* that does not exist; let FUSE know                    */
            fuse_data = dev_redir_fuse_data_dequeue(irp);
            if (fuse_data)
            {
                xfuse_devredir_cb_enum_dir_done(fuse_data->data_ptr,
                                                IoStatus);
                free(fuse_data);
            }
            devredir_irp_delete(irp);
            return;
        }

        xstream_rd_u32_le(s, irp->FileId);
        log_debug("got CID_CREATE_DIR_REQ IoStatus=0x%x FileId=%d",
                  IoStatus, irp->FileId);

        dev_redir_send_drive_dir_request(irp, DeviceId, 1, irp->pathname);
        break;

    case CID_CREATE_OPEN_REQ:
        xstream_rd_u32_le(s, irp->FileId);
        log_debug("got CID_CREATE_OPEN_REQ IoStatus=0x%x FileId=%d",
                  IoStatus, irp->FileId);
        fuse_data = dev_redir_fuse_data_dequeue(irp);
        xfuse_devredir_cb_open_file(fuse_data->data_ptr,
                                    DeviceId, irp->FileId);
        if (irp->type == S_IFDIR)
            devredir_irp_delete(irp);
        break;

    case CID_READ:
        log_debug("got CID_READ");
        xstream_rd_u32_le(s, Length);
        fuse_data = dev_redir_fuse_data_dequeue(irp);
        xfuse_devredir_cb_read_file(fuse_data->data_ptr, s->p, Length);
        break;

    case CID_WRITE:
        log_debug("got CID_WRITE");
        xstream_rd_u32_le(s, Length);
        fuse_data = dev_redir_fuse_data_dequeue(irp);
        xfuse_devredir_cb_write_file(fuse_data->data_ptr, s->p, Length);
        break;

    case CID_CLOSE:
        log_debug("got CID_CLOSE");
        log_debug("deleting irp with completion_id=%d comp_type=%d",
                  irp->CompletionId, irp->completion_type);
        devredir_irp_delete(irp);
        break;

    case CID_FILE_CLOSE:
        log_debug("got CID_FILE_CLOSE");
        fuse_data = dev_redir_fuse_data_dequeue(irp);
        xfuse_devredir_cb_file_close(fuse_data->data_ptr);
        devredir_irp_delete(irp);
        break;

    case CID_DIRECTORY_CONTROL:
        log_debug("got CID_DIRECTORY_CONTROL");

        dev_redir_proc_query_dir_response(irp, s, DeviceId,
                                          CompletionId, IoStatus);
        break;

    case CID_RMDIR_OR_FILE:
        log_debug("got CID_RMDIR_OR_FILE");
        xstream_rd_u32_le(s, irp->FileId);
        devredir_proc_cid_rmdir_or_file(irp, IoStatus);
        return;
        break;

    case CID_RMDIR_OR_FILE_RESP:
        log_debug("got CID_RMDIR_OR_FILE_RESP");
        devredir_proc_cid_rmdir_or_file_resp(irp, IoStatus);
        break;

    case CID_RENAME_FILE:
        log_debug("got CID_RENAME_FILE");
        xstream_rd_u32_le(s, irp->FileId);
        devredir_proc_cid_rename_file(irp, IoStatus);
        return;
        break;

    case CID_RENAME_FILE_RESP:
        log_debug("got CID_RENAME_FILE_RESP");
        devredir_proc_cid_rename_file_resp(irp, IoStatus);
        break;

    default:
        log_error("got unknown CompletionID: DeviceId=0x%x "
                  "CompletionId=0x%x IoStatus=0x%x",
                  DeviceId, CompletionId, IoStatus);
        break;
    }

done:

    if (fuse_data)
        free(fuse_data);

    log_debug("exiting");
}
예제 #7
0
파일: devredir.c 프로젝트: fishwgj/xrdp
void devredir_proc_client_devlist_announce_req(struct stream *s)
{
    int   i;
    int   j;
    tui32 device_count;
    tui32 device_type;
    tui32 device_data_len;
    char  preferred_dos_name[9];

    /* get number of devices being announced */
    xstream_rd_u32_le(s, device_count);

    log_debug("num of devices announced: %d", device_count);

    for (i = 0; i < device_count; i++)
    {
        xstream_rd_u32_le(s, device_type);
        xstream_rd_u32_le(s, g_device_id);

        switch (device_type)
        {
            case RDPDR_DTYP_FILESYSTEM:
                /* get preferred DOS name */
                for (j = 0; j < 8; j++)
                {
                    preferred_dos_name[j] = *s->p++;
                }

                /* DOS names that are 8 chars long are not NULL terminated */
                preferred_dos_name[8] = 0;

                /* get device data len */
                xstream_rd_u32_le(s, device_data_len);
                if (device_data_len)
                {
                    xstream_rd_string(g_full_name_for_filesystem, s,
                                     device_data_len);
                }

                log_debug("device_type=FILE_SYSTEM device_id=0x%x dosname=%s "
                          "device_data_len=%d full_name=%s", g_device_id,
                          preferred_dos_name,
                          device_data_len, g_full_name_for_filesystem);

                devredir_send_server_device_announce_resp(g_device_id);

                /* create share directory in xrdp file system;    */
                /* think of this as the mount point for this share */
                xfuse_create_share(g_device_id, preferred_dos_name);
                break;

            case RDPDR_DTYP_SMARTCARD:
                /* get preferred DOS name */
                for (j = 0; j < 8; j++)
                {
                    preferred_dos_name[j] = *s->p++;
                }

                /* DOS names that are 8 chars long are not NULL terminated */
                preferred_dos_name[8] = 0;

                /* for smart cards, device data len always 0 */

                log_debug("device_type=SMARTCARD device_id=0x%x dosname=%s "
                          "device_data_len=%d",
                          g_device_id, preferred_dos_name, device_data_len);

                devredir_send_server_device_announce_resp(g_device_id);
                scard_device_announce(g_device_id);
                break;

            /* we don't yet support these devices */
            case RDPDR_DTYP_SERIAL:
            case RDPDR_DTYP_PARALLEL:
            case RDPDR_DTYP_PRINT:
                log_debug("unsupported dev: 0x%x", device_type);
                break;
        }
    }
}
예제 #8
0
파일: devredir.c 프로젝트: fishwgj/xrdp
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;
}