~ubuntu-branches/ubuntu/edgy/rdesktop/edgy-security

« back to all changes in this revision

Viewing changes to rdpdr.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Johnston
  • Date: 2004-02-04 17:52:26 UTC
  • Revision ID: james.westby@ubuntu.com-20040204175226-87kz4bzs1nimji68
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "rdesktop.h"
 
2
 
 
3
#define IRP_MJ_CREATE           0x00
 
4
#define IRP_MJ_CLOSE            0x02
 
5
#define IRP_MJ_READ             0x03
 
6
#define IRP_MJ_WRITE            0x04
 
7
#define IRP_MJ_DEVICE_CONTROL   0x0e
 
8
 
 
9
extern char hostname[16];
 
10
extern DEVICE_FNS serial_fns;
 
11
extern DEVICE_FNS printer_fns;
 
12
 
 
13
static VCHANNEL *rdpdr_channel;
 
14
 
 
15
void
 
16
rdpdr_send_connect(void)
 
17
{
 
18
        uint8 magic[4] = "rDCC";
 
19
        STREAM s;
 
20
 
 
21
        s = channel_init(rdpdr_channel, 12);
 
22
        out_uint8a(s, magic, 4);
 
23
        out_uint16_le(s, 1);    /* unknown */
 
24
        out_uint16_le(s, 5);
 
25
        out_uint32_be(s, 0x815ed39d);   /* IP address (use 127.0.0.1) 0x815ed39d */
 
26
        s_mark_end(s);
 
27
        channel_send(s, rdpdr_channel);
 
28
}
 
29
 
 
30
void
 
31
rdpdr_send_name(void)
 
32
{
 
33
        uint8 magic[4] = "rDNC";
 
34
        uint32 hostlen = (strlen(hostname) + 1) * 2;
 
35
        STREAM s;
 
36
 
 
37
        s = channel_init(rdpdr_channel, 16 + hostlen);
 
38
        out_uint8a(s, magic, 4);
 
39
        out_uint16_le(s, 0x63); /* unknown */
 
40
        out_uint16_le(s, 0x72);
 
41
        out_uint32(s, 0);
 
42
        out_uint32_le(s, hostlen);
 
43
        rdp_out_unistr(s, hostname, hostlen - 2);
 
44
        s_mark_end(s);
 
45
        channel_send(s, rdpdr_channel);
 
46
}
 
47
 
 
48
void
 
49
rdpdr_send_available(void)
 
50
{
 
51
        uint8 magic[4] = "rDAD";
 
52
        char *driver = "Digital turbo PrintServer 20";  /* Fairly generic PostScript driver */
 
53
        char *printer = "PostScript";
 
54
        uint32 driverlen = (strlen(driver) + 1) * 2;
 
55
        uint32 printerlen = (strlen(printer) + 1) * 2;
 
56
        STREAM s;
 
57
 
 
58
        s = channel_init(rdpdr_channel, 8 + 20);
 
59
        out_uint8a(s, magic, 4);
 
60
        out_uint32_le(s, 1);    /* Number of devices */
 
61
 
 
62
#if 1
 
63
        out_uint32_le(s, 0x1);  /* Device type 0x1 - serial */
 
64
        out_uint32_le(s, 0);    /* Handle */
 
65
        out_uint8p(s, "COM2", 4);
 
66
        out_uint8s(s, 4);       /* Pad to 8 */
 
67
        out_uint32(s, 0);
 
68
#endif
 
69
#if 0
 
70
        out_uint32_le(s, 0x2);  /* Device type 0x2 - parallel */
 
71
        out_uint32_le(s, 0);
 
72
        out_uint8p(s, "LPT2", 4);
 
73
        out_uint8s(s, 4);
 
74
        out_uint32(s, 0);
 
75
#endif
 
76
#if 1
 
77
        out_uint32_le(s, 0x4);  /* Device type 0x4 - printer */
 
78
        out_uint32_le(s, 1);
 
79
        out_uint8p(s, "PRN1", 4);
 
80
        out_uint8s(s, 4);
 
81
        out_uint32_le(s, 24 + driverlen + printerlen);  /* length of extra info */
 
82
        out_uint32_le(s, 2);    /* unknown */
 
83
        out_uint8s(s, 8);       /* unknown */
 
84
        out_uint32_le(s, driverlen);    /* length of driver name */
 
85
        out_uint32_le(s, printerlen);   /* length of printer name */
 
86
        out_uint32(s, 0);       /* unknown */
 
87
        rdp_out_unistr(s, driver, driverlen - 2);
 
88
        rdp_out_unistr(s, printer, printerlen - 2);
 
89
#endif
 
90
#if 0
 
91
        out_uint32_le(s, 0x8);  /* Device type 0x8 - disk */
 
92
        out_uint32_le(s, 0);
 
93
        out_uint8p(s, "Z:", 2);
 
94
        out_uint8s(s, 6);
 
95
        out_uint32(s, 0);
 
96
#endif
 
97
#if 0
 
98
        out_uint32_le(s, 0x20); /* Device type 0x20 - smart card */
 
99
        out_uint32_le(s, 0);
 
100
        out_uint8p(s, "SCARD", 5);
 
101
        out_uint8s(s, 3);
 
102
        out_uint32(s, 0);
 
103
#endif
 
104
 
 
105
        s_mark_end(s);
 
106
        channel_send(s, rdpdr_channel);
 
107
}
 
108
 
 
109
void
 
110
rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer,
 
111
                      uint32 length)
 
112
{
 
113
        uint8 magic[4] = "rDCI";
 
114
        STREAM s;
 
115
 
 
116
        s = channel_init(rdpdr_channel, 20 + length);
 
117
        out_uint8a(s, magic, 4);
 
118
        out_uint32_le(s, device);
 
119
        out_uint32_le(s, id);
 
120
        out_uint32_le(s, status);
 
121
        out_uint32_le(s, result);
 
122
        out_uint8p(s, buffer, length);
 
123
        s_mark_end(s);
 
124
        hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
 
125
        channel_send(s, rdpdr_channel);
 
126
}
 
127
 
 
128
static void
 
129
rdpdr_process_irp(STREAM s)
 
130
{
 
131
        uint32 device, file, id, major, minor;
 
132
        NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
 
133
        uint32 result = 0, length, request, bytes_in, bytes_out;
 
134
        uint8 buffer[256];
 
135
        uint32 buffer_len = 1;
 
136
        struct stream out;
 
137
        DEVICE_FNS *fns;
 
138
 
 
139
        in_uint32_le(s, device);
 
140
        in_uint32_le(s, file);
 
141
        in_uint32_le(s, id);
 
142
        in_uint32_le(s, major);
 
143
        in_uint32_le(s, minor);
 
144
 
 
145
        memset(buffer, 0, sizeof(buffer));
 
146
 
 
147
        /* FIXME: this should probably be a more dynamic mapping */
 
148
        switch (device)
 
149
        {
 
150
                case 0:
 
151
                        fns = &serial_fns;
 
152
                case 1:
 
153
                        fns = &printer_fns;
 
154
                default:
 
155
                        error("IRP for bad device %ld\n", device);
 
156
                        return;
 
157
        }
 
158
 
 
159
        switch (major)
 
160
        {
 
161
                case IRP_MJ_CREATE:
 
162
                        if (fns->create)
 
163
                                status = fns->create(&result);
 
164
                        break;
 
165
 
 
166
                case IRP_MJ_CLOSE:
 
167
                        if (fns->close)
 
168
                                status = fns->close(file);
 
169
                        break;
 
170
 
 
171
                case IRP_MJ_READ:
 
172
                        if (fns->read)
 
173
                        {
 
174
                                if (length > sizeof(buffer))
 
175
                                        length = sizeof(buffer);
 
176
                                status = fns->read(file, buffer, length, &result);
 
177
                                buffer_len = result;
 
178
                        }
 
179
                        break;
 
180
 
 
181
                case IRP_MJ_WRITE:
 
182
                        if (fns->write)
 
183
                                status = fns->write(file, s->p, length, &result);
 
184
                        break;
 
185
 
 
186
                case IRP_MJ_DEVICE_CONTROL:
 
187
                        if (fns->device_control)
 
188
                        {
 
189
                                in_uint32_le(s, bytes_out);
 
190
                                in_uint32_le(s, bytes_in);
 
191
                                in_uint32_le(s, request);
 
192
                                in_uint8s(s, 0x14);
 
193
                                out.data = out.p = buffer;
 
194
                                out.size = sizeof(buffer);
 
195
                                status = fns->device_control(file, request, s, &out);
 
196
                                result = buffer_len = out.p - out.data;
 
197
                        }
 
198
                        break;
 
199
 
 
200
                default:
 
201
                        unimpl("IRP major=0x%x minor=0x%x\n", major, minor);
 
202
                        break;
 
203
        }
 
204
 
 
205
        rdpdr_send_completion(device, id, status, result, buffer, buffer_len);
 
206
}
 
207
 
 
208
static void
 
209
rdpdr_process(STREAM s)
 
210
{
 
211
        uint32 handle;
 
212
        uint8 *magic;
 
213
 
 
214
        printf("rdpdr_process\n");
 
215
        hexdump(s->p, s->end - s->p);
 
216
        in_uint8p(s, magic, 4);
 
217
 
 
218
        if ((magic[0] == 'r') && (magic[1] == 'D'))
 
219
        {
 
220
                if ((magic[2] == 'R') && (magic[3] == 'I'))
 
221
                {
 
222
                        rdpdr_process_irp(s);
 
223
                        return;
 
224
                }
 
225
                if ((magic[2] == 'n') && (magic[3] == 'I'))
 
226
                {
 
227
                        rdpdr_send_connect();
 
228
                        rdpdr_send_name();
 
229
                        rdpdr_send_available();
 
230
                        return;
 
231
                }
 
232
                else if ((magic[2] == 'C') && (magic[3] == 'C'))
 
233
                {
 
234
                        /* connect from server */
 
235
                        return;
 
236
                }
 
237
                else if ((magic[2] == 'r') && (magic[3] == 'd'))
 
238
                {
 
239
                        /* connect to a specific resource */
 
240
                        in_uint32(s, handle);
 
241
                        printf("Server connected to resource %d\n", handle);
 
242
                        return;
 
243
                }
 
244
        }
 
245
        unimpl("RDPDR packet type %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]);
 
246
}
 
247
 
 
248
BOOL
 
249
rdpdr_init(void)
 
250
{
 
251
        rdpdr_channel =
 
252
                channel_register("rdpdr", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP,
 
253
                                 rdpdr_process);
 
254
        return (rdpdr_channel != NULL);
 
255
}