├── .gitignore ├── .travis.yml ├── .gitattributes ├── src ├── ranges6.c ├── mst120.h ├── util-genrand.h ├── util-time.h ├── bitmap.h ├── asn.h ├── util-xmalloc.h ├── util-log.h ├── stream.h ├── util-genrand.c ├── tcp.h ├── util-time.c ├── util-sockets.c ├── util-xmalloc.c ├── workers.h ├── util-sockets.h ├── mst120.c ├── rand-blackrock.h ├── asn.c ├── ssl.h ├── rdp5.c ├── parse.h ├── rdesktop.h ├── util-log.c ├── channels.c ├── ranges6.h ├── ranges.h ├── types.h ├── ssl.c ├── orders.h ├── proto.h ├── mcs.c ├── rand-blackrock.c ├── mppc.c ├── iso.c ├── licence.c └── constants.h ├── Makefile ├── Dockerfile ├── badges ├── binary-macos.svg ├── source-linux.svg ├── binary-windows.svg └── erratarob.svg ├── vs10 ├── rdpscan.sln └── rdpscan.vcxproj ├── vs19 ├── rdpscan.sln ├── rdpscan.vcxproj.filters └── rdpscan.vcxproj └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .cvsignore 3 | Debug 4 | tmp 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | script: 4 | make 5 | 6 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.c text eol=lf 2 | *.h text eol=lf 3 | Makefile text eol=lf 4 | 5 | -------------------------------------------------------------------------------- /src/ranges6.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertdavidgraham/rdpscan/HEAD/src/ranges6.c -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | rdpscan: src/*.c src/*.h 4 | gcc -g -O1 src/*.c -lssl -lcrypto -o rdpscan 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/mst120.h: -------------------------------------------------------------------------------- 1 | /* mst120.c */ 2 | RD_BOOL mst120_check_init(void); 3 | void mst120_check(int is_send); 4 | 5 | -------------------------------------------------------------------------------- /src/util-genrand.h: -------------------------------------------------------------------------------- 1 | #ifndef GEN_RAND_H 2 | #define GEN_RAND_H 3 | 4 | void generate_random(unsigned char * random); 5 | 6 | #endif 7 | 8 | -------------------------------------------------------------------------------- /src/util-time.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_TIME_H 2 | #define UTIL_TIME_H 3 | 4 | /** 5 | * Get a relative elapsed timestamp, in nanoseconds 6 | */ 7 | unsigned long long util_microtime(void); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/bitmap.h: -------------------------------------------------------------------------------- 1 | #ifndef RDESK_BITMAP_H 2 | #define RDESK_BITMAP_H 3 | 4 | /* bitmap.c */ 5 | int bitmap_decompress(unsigned char * output, int width, int height, unsigned char * input, int size, int Bpp); 6 | 7 | #endif 8 | 9 | -------------------------------------------------------------------------------- /src/asn.h: -------------------------------------------------------------------------------- 1 | 2 | /* asn.c */ 3 | RD_BOOL ber_in_header(STREAM s, int *tagval, int *length); 4 | void ber_out_header(STREAM s, int tagval, int length); 5 | RD_BOOL ber_parse_header(STREAM s, int tagval, int *length); 6 | void ber_out_integer(STREAM s, int value); 7 | -------------------------------------------------------------------------------- /src/util-xmalloc.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_XMALLOC_H 2 | #define UTIL_XMALLOC_H 3 | #include /* size_t */ 4 | 5 | void *xmalloc(size_t size); 6 | void exit_if_null(void *ptr); 7 | char *xstrdup(const char *s); 8 | void *xrealloc(void *oldmem, size_t size); 9 | void xfree(void *mem); 10 | 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:latest as builder 2 | 3 | COPY . /app 4 | WORKDIR /app 5 | RUN apt-get update && apt-get -y upgrade && apt-get install -y libssl-dev build-essential && gcc src/*.c -lssl -lcrypto -o rdpscan 6 | 7 | FROM gcr.io/distroless/cc 8 | COPY --from=builder /app/rdpscan /app/rdpscan 9 | ENTRYPOINT ["/app/rdpscan"] 10 | -------------------------------------------------------------------------------- /src/util-log.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_LOG_H 2 | #define UTIL_LOG_H 3 | #include 4 | 5 | void RESULT(const char *format, ...); 6 | 7 | void STATUS(int lvl, const char *format, ...); 8 | void error(char *format, ...); 9 | void warning(char *format, ...); 10 | void unimpl(char *format, ...); 11 | void hexdump(unsigned char *p, size_t len); 12 | 13 | #endif 14 | 15 | -------------------------------------------------------------------------------- /src/stream.h: -------------------------------------------------------------------------------- 1 | #ifndef STREAM_H 2 | #define STREAM_H 3 | 4 | /* Parser state */ 5 | typedef struct stream 6 | { 7 | unsigned char *p; 8 | unsigned char *end; 9 | unsigned char *data; 10 | unsigned int size; 11 | 12 | /* Offsets of various headers */ 13 | unsigned char *iso_hdr; 14 | unsigned char *mcs_hdr; 15 | unsigned char *sec_hdr; 16 | unsigned char *rdp_hdr; 17 | unsigned char *channel_hdr; 18 | 19 | } *STREAM; 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /src/util-genrand.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 1 2 | #include "util-genrand.h" 3 | #include 4 | 5 | /* Generate a 32-byte random for the secure transport code. */ 6 | void 7 | generate_random(unsigned char * random) 8 | { 9 | FILE *fp; 10 | 11 | /* If we have a kernel random device, try that first */ 12 | fp = fopen("/dev/urandom", "rb"); 13 | if (fp == NULL) 14 | fp = fopen("/dev/random", "rb"); 15 | if (fp != NULL) { 16 | size_t n = fread(random, 1, 32, fp); 17 | fclose(fp); 18 | if (n == 32) 19 | return; 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/tcp.h: -------------------------------------------------------------------------------- 1 | #ifndef RDESK_TCP_H 2 | #define RDESK_TCP_H 3 | 4 | #include "stream.h" 5 | #include "types.h" 6 | 7 | extern char g_targetaddr[]; 8 | extern char g_targetport[]; 9 | 10 | /* tcp.c */ 11 | STREAM tcp_init(uint32 maxlen); 12 | void tcp_send(STREAM s); 13 | STREAM tcp_recv(STREAM s, uint32 length); 14 | RD_BOOL tcp_connect(char *server); 15 | void tcp_disconnect(void); 16 | char *tcp_get_address(void); 17 | RD_BOOL tcp_is_connected(void); 18 | void tcp_reset_state(void); 19 | RD_BOOL tcp_tls_connect(void); 20 | RD_BOOL tcp_tls_get_server_pubkey(STREAM s); 21 | void tcp_run_ui(RD_BOOL run); 22 | 23 | #endif 24 | 25 | -------------------------------------------------------------------------------- /src/util-time.c: -------------------------------------------------------------------------------- 1 | #include "util-time.h" 2 | 3 | #ifdef _WIN32 4 | #define WIN32_LEAN_AND_MEAN 5 | #include 6 | 7 | unsigned long long 8 | util_microtime(void) 9 | { 10 | unsigned long long time1 = 0, freq = 0; 11 | double seconds; 12 | QueryPerformanceCounter((LARGE_INTEGER *) &time1); 13 | QueryPerformanceFrequency((LARGE_INTEGER *)&freq); 14 | seconds = (double)time1/(double)freq; 15 | return (unsigned long long)(seconds * 1000000.0); 16 | } 17 | 18 | #else 19 | #include 20 | #include 21 | 22 | unsigned long long 23 | util_microtime(void) 24 | { 25 | int x; 26 | struct timeval tv; 27 | 28 | x = gettimeofday(&tv, 0); 29 | if (x != 0) { 30 | ;//printf("clock_gettime() err %d\n", errno); 31 | } 32 | 33 | return tv.tv_sec * 1000000ULL + tv.tv_usec; 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /badges/binary-macos.svg: -------------------------------------------------------------------------------- 1 | binarybinarymacOSmacOS -------------------------------------------------------------------------------- /badges/source-linux.svg: -------------------------------------------------------------------------------- 1 | sourcesourceLinuxLinux -------------------------------------------------------------------------------- /badges/binary-windows.svg: -------------------------------------------------------------------------------- 1 | binarybinaryWindowsWindows -------------------------------------------------------------------------------- /src/util-sockets.c: -------------------------------------------------------------------------------- 1 | 2 | #ifdef WIN32 3 | #define WIN32_LEAN_AND_MEAN 4 | #if defined(_MSC_VER) 5 | #pragma comment(lib, "Ws2_32.lib") 6 | #ifdef SSLSTATIC 7 | # pragma comment(lib, "libssl_static.lib") 8 | # pragma comment(lib, "libcrypto_static.lib") 9 | #else 10 | # pragma comment(lib, "libssl.lib") 11 | # pragma comment(lib, "libcrypto.lib") 12 | #endif 13 | 14 | #endif 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define snprintf _snprintf 20 | #define close(fd) closesocket(fd) 21 | typedef int ssize_t; 22 | #undef errno 23 | #define errno WSAGetLastError() 24 | 25 | #define strerror my_strerror 26 | 27 | const char * 28 | $strerror(int err) 29 | { 30 | static char* msg = NULL; 31 | switch (err) { 32 | default: 33 | if (msg == NULL) 34 | free(msg); 35 | FormatMessageA( 36 | FORMAT_MESSAGE_ALLOCATE_BUFFER | 37 | FORMAT_MESSAGE_FROM_SYSTEM | 38 | FORMAT_MESSAGE_IGNORE_INSERTS, 39 | NULL, 40 | err, 41 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 42 | (LPSTR)&msg, 43 | 0, NULL ); 44 | return msg; 45 | break; 46 | } 47 | } 48 | 49 | #else 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /vs10/rdpscan.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rdpscan", "rdpscan.vcxproj", "{D116CC32-BC4F-4FAD-B09C-0D6459D1C1B6}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Debug|x64 = Debug|x64 10 | Release|Win32 = Release|Win32 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {D116CC32-BC4F-4FAD-B09C-0D6459D1C1B6}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {D116CC32-BC4F-4FAD-B09C-0D6459D1C1B6}.Debug|Win32.Build.0 = Debug|Win32 16 | {D116CC32-BC4F-4FAD-B09C-0D6459D1C1B6}.Debug|x64.ActiveCfg = Debug|x64 17 | {D116CC32-BC4F-4FAD-B09C-0D6459D1C1B6}.Debug|x64.Build.0 = Debug|x64 18 | {D116CC32-BC4F-4FAD-B09C-0D6459D1C1B6}.Release|Win32.ActiveCfg = Release|Win32 19 | {D116CC32-BC4F-4FAD-B09C-0D6459D1C1B6}.Release|Win32.Build.0 = Release|Win32 20 | {D116CC32-BC4F-4FAD-B09C-0D6459D1C1B6}.Release|x64.ActiveCfg = Release|x64 21 | {D116CC32-BC4F-4FAD-B09C-0D6459D1C1B6}.Release|x64.Build.0 = Release|x64 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /src/util-xmalloc.c: -------------------------------------------------------------------------------- 1 | #include "util-xmalloc.h" 2 | #include "util-log.h" 3 | #include 4 | #include 5 | 6 | #ifndef EX_UNAVAILABLE 7 | #define EX_UNAVAILABLE (69) 8 | #endif 9 | 10 | void * 11 | xmalloc(size_t size) 12 | { 13 | void *mem = malloc(size); 14 | if (mem == NULL) 15 | { 16 | error("xmalloc %d\n", size); 17 | exit(EX_UNAVAILABLE); 18 | } 19 | return mem; 20 | } 21 | 22 | /* Exit on NULL pointer. Use to verify result from XGetImage etc */ 23 | void 24 | exit_if_null(void *ptr) 25 | { 26 | if (ptr == NULL) 27 | { 28 | error("unexpected null pointer. Out of memory?\n"); 29 | exit(EX_UNAVAILABLE); 30 | } 31 | } 32 | 33 | /* strdup */ 34 | char * 35 | xstrdup(const char *s) 36 | { 37 | char *mem; 38 | #ifdef _WIN32 39 | #define strdup(x) _strdup(x) 40 | #endif 41 | mem = strdup(s); 42 | if (mem == NULL) 43 | { 44 | perror("strdup"); 45 | exit(EX_UNAVAILABLE); 46 | } 47 | return mem; 48 | } 49 | 50 | /* realloc; exit if out of memory */ 51 | void * 52 | xrealloc(void *oldmem, size_t size) 53 | { 54 | void *mem; 55 | 56 | if (size == 0) 57 | size = 1; 58 | mem = realloc(oldmem, size); 59 | if (mem == NULL) 60 | { 61 | error("xrealloc %ld\n", size); 62 | exit(EX_UNAVAILABLE); 63 | } 64 | return mem; 65 | } 66 | 67 | /* free */ 68 | void 69 | xfree(void *mem) 70 | { 71 | free(mem); 72 | } 73 | -------------------------------------------------------------------------------- /src/workers.h: -------------------------------------------------------------------------------- 1 | #ifndef WORKERS_H 2 | #define WORKERS_H 3 | 4 | /** 5 | * In order to handle more than one target, we need to spawn 6 | * child processes. 7 | * @param progname 8 | * The name of this program, namely argv[0]. 9 | * @param filename 10 | * A file containing many IP addresses, IPv6 addresses, or 11 | * DNS names. One child process will be spawned per entry 12 | * in the file. Child processes will be spawn in the same 13 | * order as found in the file. May be NULL. 14 | * @param addresses 15 | * Addresses specified on the command-line. May be NULL. 16 | * @param debug_level 17 | * The debug level to pass to the processes for additional 18 | * debugging information, default=0. 19 | * @param rdp_port 20 | * Almost always 3389, but can be changed with the command-line 21 | * parameter --port. 22 | * @param max_children 23 | * The maximum number of child processes that can be active 24 | * at once. Modern systems should be able to handle thousands 25 | * without too much problem. 26 | * @return 27 | * This function doesn't return until all children have been 28 | * spawned and completed their scans. At that point, it's 29 | * assumed the parent program will exit having completed 30 | * its task. 31 | */ 32 | int spawn_workers(const char *progname, 33 | const char *filename, 34 | char **addresses, 35 | int debug_level, 36 | int rdp_port, 37 | unsigned max_children); 38 | 39 | #endif 40 | 41 | -------------------------------------------------------------------------------- /vs19/rdpscan.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28922.388 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rdpscan", "rdpscan.vcxproj", "{475F1C8A-F70D-45C0-95E5-EB783935277D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {475F1C8A-F70D-45C0-95E5-EB783935277D}.Debug|x64.ActiveCfg = Debug|x64 17 | {475F1C8A-F70D-45C0-95E5-EB783935277D}.Debug|x64.Build.0 = Debug|x64 18 | {475F1C8A-F70D-45C0-95E5-EB783935277D}.Debug|x86.ActiveCfg = Debug|Win32 19 | {475F1C8A-F70D-45C0-95E5-EB783935277D}.Debug|x86.Build.0 = Debug|Win32 20 | {475F1C8A-F70D-45C0-95E5-EB783935277D}.Release|x64.ActiveCfg = Release|x64 21 | {475F1C8A-F70D-45C0-95E5-EB783935277D}.Release|x64.Build.0 = Release|x64 22 | {475F1C8A-F70D-45C0-95E5-EB783935277D}.Release|x86.ActiveCfg = Release|Win32 23 | {475F1C8A-F70D-45C0-95E5-EB783935277D}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {E099EF89-8C2C-4100-B165-91C4716D17B8} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /src/util-sockets.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | A wrapper around the Sockets API to deal with 4 | Windows/POSIX differences 5 | */ 6 | #ifndef UTIL_SOCKETS_H 7 | #define UTIL_SOCKETS_H 8 | #include 9 | 10 | #ifdef _WIN32 11 | #if defined(_MSC_VER) 12 | #define WIN32_LEAN_AND_MEAN 13 | #endif 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define snprintf _snprintf 20 | #define $close(fd) closesocket(fd) 21 | typedef int ssize_t; 22 | #define $errno WSAGetLastError() 23 | #define $sleep(n) Sleep((n) * 1000) 24 | 25 | extern const char *$strerror(int err); 26 | 27 | #define $EWOULDBLOCK WSAEWOULDBLOCK 28 | #define $ECONNRESET WSAECONNRESET 29 | #define $EINTR WSAEINTR 30 | #define $EINPROGRESS WSAEINPROGRESS 31 | #define $ETIMEDOUT WSAETIMEDOUT 32 | #define $ECONNABORTED WSAECONNABORTED 33 | #define $ECONNREFUSED WSAECONNREFUSED 34 | #define $EBADF WSAEBADF 35 | #define $ENETUNREACH WSAENETUNREACH 36 | #define $EHOSTUNREACH WSAEHOSTUNREACH 37 | #define $EACCES WSAEACCES 38 | 39 | #else 40 | #include /* select read write close */ 41 | #include /* socket connect setsockopt */ 42 | #include /* timeval */ 43 | #include /* gethostbyname */ 44 | #include /* sockaddr_in */ 45 | #include /* TCP_NODELAY */ 46 | #include /* inet_addr */ 47 | #include 48 | #include 49 | #define $EWOULDBLOCK EWOULDBLOCK 50 | #define $ECONNRESET ECONNRESET 51 | #define $EINTR EINTR 52 | #define $EINPROGRESS EINPROGRESS 53 | #define $ETIMEDOUT ETIMEDOUT 54 | #define $ECONNABORTED ECONNABORTED 55 | #define $ECONNREFUSED ECONNREFUSED 56 | #define $EBADF EBADF 57 | #define $ENETUNREACH ENETUNREACH 58 | #define $EHOSTUNREACH EHOSTUNREACH 59 | #define $EACCES EACCES 60 | #define $strerror(err) strerror(err) 61 | #define $errno errno 62 | #define $close(fd) close(fd) 63 | #define $sleep(n) sleep(n) 64 | #endif 65 | 66 | #ifndef INADDR_NONE 67 | #define INADDR_NONE ((unsigned long) -1) 68 | #endif 69 | 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/mst120.c: -------------------------------------------------------------------------------- 1 | #include "rdesktop.h" 2 | #include "util-xmalloc.h" 3 | #include "util-log.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #ifndef _WIN32 11 | #include 12 | #endif 13 | 14 | #define MST120_SEND_MAX 5 15 | const unsigned MST120_TIMEOUT = 6; // in seconds 16 | 17 | static VCHANNEL *mst120_channel; 18 | static int g_check_count; 19 | time_t g_first_check; 20 | 21 | static void 22 | mst120_process(STREAM s) 23 | { 24 | // pass 25 | } 26 | 27 | RD_BOOL 28 | mst120_check_init() 29 | { 30 | //printf("[+] Registering MS_T120 channel.\n"); 31 | 32 | g_check_count = 0; 33 | g_first_check = 0; 34 | 35 | mst120_channel = channel_register("MS_T120", 36 | CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP, 37 | mst120_process); 38 | 39 | return (mst120_channel != NULL); 40 | } 41 | 42 | void 43 | mst120_send_check_packet(size_t size, size_t offset) 44 | { 45 | char *buff = xmalloc(size); 46 | STREAM s; 47 | static int is_printed = 0; 48 | 49 | if (is_printed++ == 0) 50 | { 51 | STATUS(1, "[+] Sending MS_T120 check packet\n"); 52 | } 53 | else 54 | { 55 | STATUS(4, "[+] Sending MS_T120 check packet (size: 0x%lx - offset: 0x%lx)\n", 56 | size, offset); 57 | } 58 | 59 | memset(buff, 0, size); 60 | 61 | buff[offset] = 2; 62 | 63 | s = channel_init(mst120_channel, (unsigned)size); 64 | out_uint8p(s, buff, size); 65 | s_mark_end(s); 66 | channel_send(s, mst120_channel); 67 | 68 | xfree(buff); 69 | } 70 | 71 | void 72 | mst120_check(int is_send) 73 | { 74 | if (g_check_count > MST120_SEND_MAX) 75 | { 76 | static int is_printed = 0; 77 | if (is_printed++ == 0) 78 | STATUS(1, "[-] Max sends reached, waiting...\n"); 79 | 80 | if (g_first_check == 0) 81 | g_first_check = time(0); 82 | 83 | if ((time(0) - g_first_check) > MST120_TIMEOUT) 84 | { 85 | RESULT("SAFE - Target appears patched\n"); 86 | exit(0); 87 | } 88 | return; 89 | } 90 | 91 | if (is_send) 92 | { 93 | ++g_check_count; 94 | mst120_send_check_packet(0x20, 8); 95 | mst120_send_check_packet(0x10, 4); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/rand-blackrock.h: -------------------------------------------------------------------------------- 1 | #ifndef RAND_BLACKROCK_H 2 | #define RAND_BLACKROCK_H 3 | #include 4 | 5 | struct BlackRock { 6 | uint64_t range; 7 | uint64_t a; 8 | uint64_t b; 9 | uint64_t seed; 10 | unsigned rounds; 11 | uint64_t a_bits; 12 | uint64_t a_mask; 13 | uint64_t b_bits; 14 | uint64_t b_mask; 15 | }; 16 | 17 | /** 18 | * Initializes a structure for shuffling numbers within 19 | * a range. 20 | * 21 | * @param range 22 | * The size of the range of numbers needing to be 23 | * shuffled/randomized. 24 | */ 25 | void 26 | blackrock_init(struct BlackRock *br, uint64_t range, uint64_t seed, unsigned rounds); 27 | void 28 | blackrock2_init(struct BlackRock *br, uint64_t range, uint64_t seed, unsigned rounds); 29 | 30 | /** 31 | * Given a number within a range, produce a different number with 32 | * the same range. There is a 1-to-1 mapping between the two, 33 | * so when linearly incrementing through the range, the output 34 | * of this function won't repeat. In other words, encrypt the index variable. 35 | * @param br 36 | * The randomization parameters created with 'blackrock_init()' 37 | * @param index 38 | * An input within the specified range. We call it an 'index' variable 39 | * because that's how we intend to use this function, shuffling a 40 | * monotonically increasing index variable, but in truth, any sort 41 | * of integer can be used. This must be within the 'range' specified 42 | * during the call to blackrock_init(), or the results are undefined. 43 | * @return 44 | * A one-to-one matching index that's in the same range. 45 | */ 46 | uint64_t 47 | blackrock_shuffle(const struct BlackRock *br, uint64_t index); 48 | uint64_t 49 | blackrock2_shuffle(const struct BlackRock *br, uint64_t index); 50 | 51 | /** 52 | * The reverse of the shuffle function above: given the shuffled/ecnrypted 53 | * integer, return the original index value before the shuffling/encryption. 54 | */ 55 | uint64_t 56 | blackrock_unshuffle(const struct BlackRock *br, uint64_t m); 57 | uint64_t 58 | blackrock2_unshuffle(const struct BlackRock *br, uint64_t m); 59 | 60 | 61 | /** 62 | * Do a regression test. 63 | * @return 64 | * 0 of the regression test succeeds or non-zero if it fails 65 | */ 66 | int 67 | blackrock_selftest(void); 68 | int 69 | blackrock2_selftest(void); 70 | 71 | /** 72 | * Do a benchmark of this module regression test. 73 | */ 74 | void 75 | blackrock_benchmark(unsigned rounds); 76 | void 77 | blackrock2_benchmark(unsigned rounds); 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /badges/erratarob.svg: -------------------------------------------------------------------------------- 1 | Follow @erratarobFollow @erratarob40k40k -------------------------------------------------------------------------------- /src/asn.c: -------------------------------------------------------------------------------- 1 | /* -*- c-basic-offset: 8 -*- 2 | rdesktop: A Remote Desktop Protocol client. 3 | ASN.1 utility functions 4 | Copyright 2012 Henrik Andersson for Cendio AB 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "rdesktop.h" 21 | #include "util-log.h" 22 | 23 | 24 | /* Parse an ASN.1 BER header */ 25 | RD_BOOL 26 | ber_parse_header(STREAM s, int tagval, int *length) 27 | { 28 | int tag, len; 29 | 30 | if (tagval > 0xff) 31 | { 32 | in_uint16_be(s, tag); 33 | } 34 | else 35 | { 36 | in_uint8(s, tag); 37 | } 38 | 39 | if (tag != tagval) 40 | { 41 | error("expected tag %d, got %d\n", tagval, tag); 42 | return False; 43 | } 44 | 45 | in_uint8(s, len); 46 | 47 | if (len & 0x80) 48 | { 49 | len &= ~0x80; 50 | *length = 0; 51 | while (len--) 52 | next_be(s, *length); 53 | } 54 | else 55 | *length = len; 56 | 57 | return s_check(s); 58 | } 59 | 60 | /* Output an ASN.1 BER header */ 61 | void 62 | ber_out_header(STREAM s, int tagval, int length) 63 | { 64 | if (tagval > 0xff) 65 | { 66 | out_uint16_be(s, tagval); 67 | } 68 | else 69 | { 70 | out_uint8(s, tagval); 71 | } 72 | 73 | if (length >= 0x80) 74 | { 75 | out_uint8(s, 0x82); 76 | out_uint16_be(s, length); 77 | } 78 | else 79 | out_uint8(s, length); 80 | } 81 | 82 | /* Output an ASN.1 BER integer */ 83 | void 84 | ber_out_integer(STREAM s, int value) 85 | { 86 | ber_out_header(s, BER_TAG_INTEGER, 2); 87 | out_uint16_be(s, value); 88 | } 89 | 90 | RD_BOOL 91 | ber_in_header(STREAM s, int *tagval, int *decoded_len) 92 | { 93 | in_uint8(s, *tagval); 94 | in_uint8(s, *decoded_len); 95 | 96 | if (*decoded_len < 0x80) 97 | return True; 98 | else if (*decoded_len == 0x81) 99 | { 100 | in_uint8(s, *decoded_len); 101 | return True; 102 | } 103 | else if (*decoded_len == 0x82) 104 | { 105 | in_uint16_be(s, *decoded_len); 106 | return True; 107 | } 108 | 109 | return False; 110 | } 111 | -------------------------------------------------------------------------------- /src/ssl.h: -------------------------------------------------------------------------------- 1 | /* -*- c-basic-offset: 8 -*- 2 | rdesktop: A Remote Desktop Protocol client. 3 | Secure sockets abstraction layer 4 | Copyright (C) Matthew Chapman 1999-2008 5 | Copyright (C) Jay Sorg 2006-2008 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef _RDSSL_H 22 | #define _RDSSL_H 23 | 24 | #include "openssl/rc4.h" 25 | #include "openssl/md5.h" 26 | #include "openssl/sha.h" 27 | #include "openssl/bn.h" 28 | #include "openssl/x509v3.h" 29 | #include "openssl/hmac.h" 30 | 31 | #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800f) 32 | #define D2I_X509_CONST const 33 | #else 34 | #define D2I_X509_CONST 35 | #endif 36 | 37 | #define RDSSL_RC4 RC4_KEY 38 | #define RDSSL_SHA1 SHA_CTX 39 | #define RDSSL_MD5 MD5_CTX 40 | #define RDSSL_CERT X509 41 | #define RDSSL_RKEY RSA 42 | 43 | void rdssl_sha1_init(RDSSL_SHA1 * sha1); 44 | void rdssl_sha1_update(RDSSL_SHA1 * sha1, uint8 * data, uint32 len); 45 | void rdssl_sha1_final(RDSSL_SHA1 * sha1, uint8 * out_data); 46 | void rdssl_md5_init(RDSSL_MD5 * md5); 47 | void rdssl_md5_update(RDSSL_MD5 * md5, uint8 * data, uint32 len); 48 | void rdssl_md5_final(RDSSL_MD5 * md5, uint8 * out_data); 49 | void rdssl_rc4_set_key(RDSSL_RC4 * rc4, uint8 * key, uint32 len); 50 | void rdssl_rc4_crypt(RDSSL_RC4 * rc4, uint8 * in_data, uint8 * out_data, uint32 len); 51 | void rdssl_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus, 52 | uint8 * exponent); 53 | RDSSL_CERT *rdssl_cert_read(uint8 * data, uint32 len); 54 | void rdssl_cert_free(RDSSL_CERT * cert); 55 | RDSSL_RKEY *rdssl_cert_to_rkey(RDSSL_CERT * cert, uint32 * key_len); 56 | RD_BOOL rdssl_certs_ok(RDSSL_CERT * server_cert, RDSSL_CERT * cacert); 57 | int rdssl_cert_print_fp(FILE * fp, RDSSL_CERT * cert); 58 | void rdssl_rkey_free(RDSSL_RKEY * rkey); 59 | int rdssl_rkey_get_exp_mod(RDSSL_RKEY * rkey, uint8 * exponent, uint32 max_exp_len, uint8 * modulus, 60 | uint32 max_mod_len); 61 | RD_BOOL rdssl_sig_ok(uint8 * exponent, uint32 exp_len, uint8 * modulus, uint32 mod_len, 62 | uint8 * signature, uint32 sig_len); 63 | 64 | void rdssl_hmac_md5(const void *key, int key_len, 65 | const unsigned char *msg, int msg_len, unsigned char *md); 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/rdp5.c: -------------------------------------------------------------------------------- 1 | /* -*- c-basic-offset: 8 -*- 2 | rdesktop: A Remote Desktop Protocol client. 3 | Protocol services - RDP5 short form PDU processing 4 | Copyright (C) Matthew Chapman 1999-2008 5 | Copyright 2003-2008 Erik Forsberg for Cendio AB 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include "rdesktop.h" 22 | #include "util-xmalloc.h" 23 | #include "util-log.h" 24 | #include 25 | 26 | extern uint8 *g_next_packet; 27 | 28 | extern RDPCOMP g_mppc_dict; 29 | 30 | void 31 | rdp5_process(STREAM s) 32 | { 33 | uint16 length, count, x, y; 34 | uint8 type, ctype; 35 | uint8 *next; 36 | 37 | uint32 roff, rlen; 38 | struct stream *ns = &(g_mppc_dict.ns); 39 | struct stream *ts; 40 | 41 | #if 0 42 | printf("RDP5 data:\n"); 43 | hexdump(s->p, s->end - s->p); 44 | #endif 45 | 46 | //ui_begin_update(); 47 | while (s->p < s->end) 48 | { 49 | in_uint8(s, type); 50 | if (type & RDP5_COMPRESSED) 51 | { 52 | in_uint8(s, ctype); 53 | in_uint16_le(s, length); 54 | type ^= RDP5_COMPRESSED; 55 | } 56 | else 57 | { 58 | ctype = 0; 59 | in_uint16_le(s, length); 60 | } 61 | g_next_packet = next = s->p + length; 62 | 63 | if (ctype & RDP_MPPC_COMPRESSED) 64 | { 65 | if (mppc_expand(s->p, length, ctype, &roff, &rlen) == -1) 66 | error("error while decompressing packet\n"); 67 | 68 | /* allocate memory and copy the uncompressed data into the temporary stream */ 69 | ns->data = (uint8 *) xrealloc(ns->data, rlen); 70 | 71 | memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen); 72 | 73 | ns->size = rlen; 74 | ns->end = (ns->data + ns->size); 75 | ns->p = ns->data; 76 | ns->rdp_hdr = ns->p; 77 | 78 | ts = ns; 79 | } 80 | else 81 | ts = s; 82 | 83 | switch (type) 84 | { 85 | case 0: /* update orders */ 86 | in_uint16_le(ts, count); 87 | process_orders(ts, count); 88 | break; 89 | case 1: /* update bitmap */ 90 | in_uint8s(ts, 2); /* part length */ 91 | process_bitmap_updates(ts); 92 | break; 93 | case 2: /* update palette */ 94 | in_uint8s(ts, 2); /* uint16 = 2 */ 95 | process_palette(ts); 96 | break; 97 | case 3: /* update synchronize */ 98 | break; 99 | case 5: /* null pointer */ 100 | //ui_set_null_cursor(); 101 | break; 102 | case 6: /* default pointer */ 103 | break; 104 | case 8: /* pointer position */ 105 | in_uint16_le(ts, x); 106 | in_uint16_le(ts, y); 107 | if (s_check(ts)) 108 | ;//ui_move_pointer(x, y); 109 | break; 110 | case 9: /* color pointer */ 111 | process_colour_pointer_pdu(ts); 112 | break; 113 | case 10: /* cached pointer */ 114 | process_cached_pointer_pdu(ts); 115 | break; 116 | case 11: 117 | process_new_pointer_pdu(ts); 118 | break; 119 | default: 120 | unimpl("RDP5 opcode %d\n", type); 121 | } 122 | 123 | s->p = next; 124 | } 125 | //ui_end_update(); 126 | } 127 | -------------------------------------------------------------------------------- /src/parse.h: -------------------------------------------------------------------------------- 1 | /* 2 | rdesktop: A Remote Desktop Protocol client. 3 | Parsing primitives 4 | Copyright (C) Matthew Chapman 1999-2008 5 | Copyright 2012 Henrik Andersson for Cendio AB 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | 22 | #define s_push_layer(s,h,n) { (s)->h = (s)->p; (s)->p += n; } 23 | #define s_pop_layer(s,h) (s)->p = (s)->h; 24 | #define s_mark_end(s) (s)->end = (s)->p; 25 | #define s_check(s) ((s)->p <= (s)->end) 26 | #define s_check_rem(s,n) ((s)->p + n <= (s)->end) 27 | #define s_check_end(s) ((s)->p == (s)->end) 28 | #define s_length(s) ((s)->end - (s)->data) 29 | #define s_reset(s) ((s)->end = (s)->p = (s)->data) 30 | 31 | #if defined(L_ENDIAN) && !defined(NEED_ALIGN) 32 | #define in_uint16_le(s,v) { v = *(uint16 *)((s)->p); (s)->p += 2; } 33 | #define in_uint32_le(s,v) { v = *(uint32 *)((s)->p); (s)->p += 4; } 34 | #define out_uint16_le(s,v) { *(uint16 *)((s)->p) = v; (s)->p += 2; } 35 | #define out_uint32_le(s,v) { *(unsigned *)((s)->p) = v; (s)->p += 4; } 36 | 37 | #else 38 | #define in_uint16_le(s,v) { v = *((s)->p++); v += *((s)->p++) << 8; } 39 | #define in_uint32_le(s,v) { in_uint16_le(s,v) \ 40 | v += *((s)->p++) << 16; v += *((s)->p++) << 24; } 41 | #define out_uint16_le(s,v) { *((s)->p++) = (v) & 0xff; *((s)->p++) = ((v) >> 8) & 0xff; } 42 | #define out_uint32_le(s,v) { out_uint16_le(s, (v) & 0xffff); out_uint16_le(s, ((v) >> 16) & 0xffff); } 43 | #endif 44 | 45 | #if defined(B_ENDIAN) && !defined(NEED_ALIGN) 46 | #define in_uint16_be(s,v) { v = *(uint16 *)((s)->p); (s)->p += 2; } 47 | #define in_uint32_be(s,v) { v = *(uint32 *)((s)->p); (s)->p += 4; } 48 | #define out_uint16_be(s,v) { *(uint16 *)((s)->p) = v; (s)->p += 2; } 49 | #define out_uint32_be(s,v) { *(uint32 *)((s)->p) = v; (s)->p += 4; } 50 | 51 | #define B_ENDIAN_PREFERRED 52 | #define in_uint16(s,v) in_uint16_be(s,v) 53 | #define in_uint32(s,v) in_uint32_be(s,v) 54 | #define out_uint16(s,v) out_uint16_be(s,v) 55 | #define out_uint32(s,v) out_uint32_be(s,v) 56 | 57 | #else 58 | #define in_uint16_be(s,v) { v = *((s)->p++); next_be(s,v); } 59 | #define in_uint32_be(s,v) { in_uint16_be(s,v); next_be(s,v); next_be(s,v); } 60 | #define out_uint16_be(s,v) { *((s)->p++) = ((v) >> 8) & 0xff; *((s)->p++) = (v) & 0xff; } 61 | #define out_uint32_be(s,v) { out_uint16_be(s, ((v) >> 16) & 0xffff); out_uint16_be(s, (v) & 0xffff); } 62 | #endif 63 | 64 | #ifndef B_ENDIAN_PREFERRED 65 | #define in_uint16(s,v) in_uint16_le(s,v) 66 | #define in_uint32(s,v) in_uint32_le(s,v) 67 | #define out_uint16(s,v) out_uint16_le(s,v) 68 | #define out_uint32(s,v) out_uint32_le(s,v) 69 | #endif 70 | 71 | #define in_uint8(s,v) v = *((s)->p++); 72 | #define in_uint8p(s,v,n) { v = (s)->p; (s)->p += n; } 73 | #define in_uint8a(s,v,n) { memcpy(v,(s)->p,n); (s)->p += n; } 74 | #define in_uint8s(s,n) (s)->p += n; 75 | #define out_uint8(s,v) *((s)->p++) = v; 76 | #define out_uint8p(s,v,n) { memcpy((s)->p,v,n); (s)->p += n; } 77 | #define out_uint8a(s,v,n) out_uint8p(s,v,n); 78 | #define out_uint8s(s,n) { memset((s)->p,0,n); (s)->p += n; } 79 | 80 | #define next_be(s,v) v = ((v) << 8) + *((s)->p++); 81 | -------------------------------------------------------------------------------- /src/rdesktop.h: -------------------------------------------------------------------------------- 1 | /* 2 | rdesktop: A Remote Desktop Protocol client. 3 | Master include file 4 | Copyright (C) Matthew Chapman 1999-2008 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | #include 20 | 21 | #if 0 22 | #ifdef _WIN32 23 | #else 24 | # include 25 | # include 26 | # include 27 | # include 28 | #endif 29 | #endif 30 | 31 | /* standard exit codes */ 32 | #ifndef EX_OK 33 | #define EX_OK 0 34 | #endif 35 | #ifndef EX_USAGE 36 | #define EX_USAGE 64 37 | #endif 38 | #ifndef EX_DATAERR 39 | #define EX_DATAERR 65 40 | #endif 41 | #ifndef EX_NOINPUT 42 | #define EX_NOINPUT 66 43 | #endif 44 | #ifndef EX_NOUSER 45 | #define EX_NOUSER 67 46 | #endif 47 | #ifndef EX_NOHOST 48 | #define EX_NOHOST 68 49 | #endif 50 | #ifndef EX_UNAVAILABLE 51 | #define EX_UNAVAILABLE 69 52 | #endif 53 | #ifndef EX_SOFTWARE 54 | #define EX_SOFTWARE 70 55 | #endif 56 | #ifndef EX_OSERR 57 | #define EX_OSERR 71 58 | #endif 59 | #ifndef EX_OSFILE 60 | #define EX_OSFILE 72 61 | #endif 62 | #ifndef EX_CANTCREAT 63 | #define EX_CANTCREAT 73 64 | #endif 65 | #ifndef EX_IOERR 66 | #define EX_IOERR 74 67 | #endif 68 | #ifndef EX_TEMPFAIL 69 | #define EX_TEMPFAIL 75 70 | #endif 71 | #ifndef EX_PROTOCOL 72 | #define EX_PROTOCOL 76 73 | #endif 74 | #ifndef EX_NOPERM 75 | #define EX_NOPERM 77 76 | #endif 77 | #ifndef EX_CONFIG 78 | #define EX_CONFIG 78 79 | #endif 80 | 81 | /* rdesktop specific exit codes, lined up with disconnect PDU reasons */ 82 | #define EXRD_API_DISCONNECT 1 83 | #define EXRD_API_LOGOFF 2 84 | #define EXRD_IDLE_TIMEOUT 3 85 | #define EXRD_LOGON_TIMEOUT 4 86 | #define EXRD_REPLACED 5 87 | #define EXRD_OUT_OF_MEM 6 88 | #define EXRD_DENIED 7 89 | #define EXRD_DENIED_FIPS 8 90 | #define EXRD_INSUFFICIENT_PRIVILEGES 9 91 | #define EXRD_FRESH_CREDENTIALS_REQUIRED 10 92 | #define EXRD_RPC_DISCONNECT_BY_USER 11 93 | #define EXRD_DISCONNECT_BY_USER 12 94 | #define EXRD_LIC_INTERNAL 16 95 | #define EXRD_LIC_NOSERVER 17 96 | #define EXRD_LIC_NOLICENSE 18 97 | #define EXRD_LIC_MSG 19 98 | #define EXRD_LIC_HWID 20 99 | #define EXRD_LIC_CLIENT 21 100 | #define EXRD_LIC_NET 22 101 | #define EXRD_LIC_PROTO 23 102 | #define EXRD_LIC_ENC 24 103 | #define EXRD_LIC_UPGRADE 25 104 | #define EXRD_LIC_NOREMOTE 26 105 | 106 | /* other exit codes */ 107 | #define EXRD_WINDOW_CLOSED 62 108 | #define EXRD_UNKNOWN 63 109 | 110 | #undef DEBUG 111 | #ifdef WITH_DEBUG 112 | #define DEBUG(args) printf args; 113 | #else 114 | #undef DEBUG 115 | #define DEBUG(args) 116 | #endif 117 | 118 | #ifdef WITH_DEBUG_KBD 119 | #define DEBUG_KBD(args) printf args; 120 | #else 121 | #define DEBUG_KBD(args) 122 | #endif 123 | 124 | #ifdef WITH_DEBUG_RDP5 125 | #define DEBUG_RDP5(args) printf args; 126 | #else 127 | #define DEBUG_RDP5(args) 128 | #endif 129 | 130 | #ifdef WITH_DEBUG_CLIPBOARD 131 | #define DEBUG_CLIPBOARD(args) printf args; 132 | #else 133 | #define DEBUG_CLIPBOARD(args) 134 | #endif 135 | 136 | #ifdef WITH_DEBUG_SOUND 137 | #define DEBUG_SOUND(args) printf args; 138 | #else 139 | #define DEBUG_SOUND(args) 140 | #endif 141 | 142 | #ifdef WITH_DEBUG_CHANNEL 143 | #define DEBUG_CHANNEL(args) printf args; 144 | #else 145 | #define DEBUG_CHANNEL(args) 146 | #endif 147 | 148 | #ifdef WITH_DEBUG_SCARD 149 | #define DEBUG_SCARD(args) printf args; 150 | #else 151 | #define DEBUG_SCARD(args) 152 | #endif 153 | 154 | #define STRNCPY(dst,src,n) { strncpy(dst,src,n-1); dst[n-1] = 0; } 155 | 156 | #ifndef MIN 157 | #define MIN(x,y) (((x) < (y)) ? (x) : (y)) 158 | #endif 159 | 160 | #ifndef MAX 161 | #define MAX(x,y) (((x) > (y)) ? (x) : (y)) 162 | #endif 163 | 164 | /* timeval macros */ 165 | #ifndef timerisset 166 | #define timerisset(tvp)\ 167 | ((tvp)->tv_sec || (tvp)->tv_usec) 168 | #endif 169 | #ifndef timercmp 170 | #define timercmp(tvp, uvp, cmp)\ 171 | ((tvp)->tv_sec cmp (uvp)->tv_sec ||\ 172 | (tvp)->tv_sec == (uvp)->tv_sec &&\ 173 | (tvp)->tv_usec cmp (uvp)->tv_usec) 174 | #endif 175 | #ifndef timerclear 176 | #define timerclear(tvp)\ 177 | ((tvp)->tv_sec = (tvp)->tv_usec = 0) 178 | #endif 179 | 180 | /* If configure does not define the endianess, try 181 | to find it out */ 182 | #if !defined(L_ENDIAN) && !defined(B_ENDIAN) 183 | #if __BYTE_ORDER == __LITTLE_ENDIAN 184 | #define L_ENDIAN 185 | #elif __BYTE_ORDER == __BIG_ENDIAN 186 | #define B_ENDIAN 187 | #else 188 | #error Unknown endianness. Edit rdesktop.h. 189 | #endif 190 | #endif /* B_ENDIAN, L_ENDIAN from configure */ 191 | 192 | /* No need for alignment on x86 and amd64 */ 193 | #if !defined(NEED_ALIGN) 194 | #if !(defined(__x86__) || defined(__x86_64__) || \ 195 | defined(__AMD64__) || defined(_M_IX86) || \ 196 | defined(__i386__)) 197 | #define NEED_ALIGN 198 | #endif 199 | #endif 200 | 201 | #include "parse.h" 202 | #include "constants.h" 203 | #include "types.h" 204 | 205 | #ifndef MAKE_PROTO 206 | #include "proto.h" 207 | #endif 208 | -------------------------------------------------------------------------------- /vs19/rdpscan.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 61 | Source Files 62 | 63 | 64 | Source Files 65 | 66 | 67 | Source Files 68 | 69 | 70 | Source Files 71 | 72 | 73 | Source Files 74 | 75 | 76 | Source Files 77 | 78 | 79 | Source Files 80 | 81 | 82 | Source Files 83 | 84 | 85 | Source Files 86 | 87 | 88 | 89 | 90 | Source Files 91 | 92 | 93 | Source Files 94 | 95 | 96 | Source Files 97 | 98 | 99 | Source Files 100 | 101 | 102 | Source Files 103 | 104 | 105 | Source Files 106 | 107 | 108 | Source Files 109 | 110 | 111 | Source Files 112 | 113 | 114 | Source Files 115 | 116 | 117 | Source Files 118 | 119 | 120 | Source Files 121 | 122 | 123 | Source Files 124 | 125 | 126 | Source Files 127 | 128 | 129 | Source Files 130 | 131 | 132 | Source Files 133 | 134 | 135 | Source Files 136 | 137 | 138 | Source Files 139 | 140 | 141 | Source Files 142 | 143 | 144 | Source Files 145 | 146 | 147 | Source Files 148 | 149 | 150 | -------------------------------------------------------------------------------- /src/util-log.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 1 2 | #include "util-log.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef WIN32 10 | #include /* alloca() */ 11 | #define snprintf _snprintf 12 | #endif 13 | 14 | int g_log_level = 0; 15 | extern char g_targetaddr[]; 16 | extern char g_targetport[]; 17 | 18 | void 19 | RESULT(const char *format, ...) 20 | { 21 | va_list ap; 22 | char *newfmt; 23 | int newfmt_length; 24 | int x; 25 | char datetime[128]; 26 | time_t now = time(0); 27 | struct tm *tm = NULL; 28 | extern int g_is_gmtime; 29 | extern int g_is_localtime; 30 | 31 | 32 | if (g_is_gmtime) { 33 | tm = gmtime(&now); 34 | } else if (g_is_localtime) 35 | tm = localtime(&now); 36 | 37 | if (tm) 38 | strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S - ", tm); 39 | else 40 | datetime[0] = '\0'; 41 | 42 | /* We want a single atomic write, due to multiple processes trying 43 | * to write output at the same time. Therefore, instead of multiple 44 | * fprintf() statements, we are going to combine into a single 45 | * statement. This means creating a new format string. */ 46 | newfmt_length = 14+1; /* strlen("[-] []: - ") */ 47 | newfmt_length += (int)strlen(g_targetaddr); 48 | newfmt_length += (int)strlen(format); 49 | newfmt_length += (int)strlen(datetime); 50 | 51 | /* Kludge: format string attack protection */ 52 | { 53 | size_t i; 54 | for (i=0; g_targetaddr[i]; i++) { 55 | if (g_targetaddr[i] == '%') 56 | g_targetaddr[i] = ' '; 57 | } 58 | } 59 | 60 | /* Create the new format string */ 61 | newfmt = alloca(newfmt_length); 62 | x = snprintf(newfmt, newfmt_length, "%s%s - %s", datetime, g_targetaddr, format); 63 | 64 | /* Now do the single atomi print */ 65 | va_start(ap, format); 66 | vfprintf(stdout, newfmt, ap); 67 | va_end(ap); 68 | 69 | exit(0); 70 | } 71 | 72 | static void 73 | vSTATUS(int lvl, char plus, const char *format, va_list ap) 74 | { 75 | char *newfmt; 76 | int newfmt_length; 77 | int x; 78 | 79 | /* Only print messages that are at the current diag-level or lower. 80 | * Thus, higher settings of the diagnostics level will create more 81 | * verbose output */ 82 | if (lvl > g_log_level) 83 | return; 84 | 85 | /* We are going to print a status indicator of [+], [-], or [ ] 86 | * for all output, even if the caller didn't specify one */ 87 | if (format[0] == '[' && format[1] != '\0' && format[2] == ']' && format[3] == ' ') { 88 | plus = format[1]; 89 | if (plus == '%') 90 | plus = '*'; 91 | format += 4; 92 | } 93 | 94 | /* We want a single atomic write, due to multiple processes trying 95 | * to write output at the same time. Therefore, instead of multiple 96 | * fprintf() statements, we are going to combine into a single 97 | * statement. This means creating a new format string. */ 98 | newfmt_length = 14+1; /* strlen("[-] []: - ") */ 99 | newfmt_length += (int)strlen(g_targetaddr); 100 | newfmt_length += (int)strlen(g_targetport); 101 | newfmt_length += (int)strlen(format); 102 | 103 | /* Kludge: format string attack protection */ 104 | { 105 | size_t i; 106 | for (i=0; g_targetaddr[i]; i++) { 107 | if (g_targetaddr[i] == '%') 108 | g_targetaddr[i] = ' '; 109 | } 110 | for (i=0; g_targetport[i]; i++) { 111 | if (g_targetaddr[i] == '%') 112 | g_targetaddr[i] = ' '; 113 | } 114 | } 115 | 116 | /* Create the new format string */ 117 | newfmt = alloca(newfmt_length); 118 | x = snprintf(newfmt, newfmt_length, "[%c] [%s]:%s - %s", plus, g_targetaddr, g_targetport, format); 119 | 120 | /* Now do the single atomi print */ 121 | vfprintf(stderr, newfmt, ap); 122 | fflush(stderr); 123 | } 124 | 125 | void 126 | STATUS(int lvl, const char *format, ...) 127 | { 128 | va_list ap; 129 | va_start(ap, format); 130 | vSTATUS(lvl, ' ', format, ap); 131 | va_end(ap); 132 | } 133 | 134 | /* report an error */ 135 | void 136 | error(char *format, ...) 137 | { 138 | va_list ap; 139 | va_start(ap, format); 140 | vSTATUS(0, '-', format, ap); 141 | va_end(ap); 142 | } 143 | 144 | /* report a warning */ 145 | void 146 | warning(char *format, ...) 147 | { 148 | va_list ap; 149 | va_start(ap, format); 150 | vSTATUS(1, ' ', format, ap); 151 | va_end(ap); 152 | } 153 | 154 | /* report an unimplemented protocol feature */ 155 | void 156 | unimpl(char *format, ...) 157 | { 158 | va_list ap; 159 | va_start(ap, format); 160 | vSTATUS(1, '#', format, ap); 161 | va_end(ap); 162 | } 163 | 164 | /* produce a hex dump */ 165 | void 166 | hexdump(unsigned char *p, size_t len) 167 | { 168 | unsigned char *line = p; 169 | size_t i, thisline; 170 | size_t offset = 0; 171 | 172 | while (offset < len) 173 | { 174 | printf("%04x ", (unsigned)offset); 175 | thisline = len - offset; 176 | if (thisline > 16) 177 | thisline = 16; 178 | 179 | for (i = 0; i < thisline; i++) 180 | printf("%02x ", line[i]); 181 | 182 | for (; i < 16; i++) 183 | printf(" "); 184 | 185 | for (i = 0; i < thisline; i++) 186 | printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); 187 | 188 | printf("\n"); 189 | offset += thisline; 190 | line += thisline; 191 | } 192 | } 193 | 194 | 195 | -------------------------------------------------------------------------------- /src/channels.c: -------------------------------------------------------------------------------- 1 | /* -*- c-basic-offset: 8 -*- 2 | rdesktop: A Remote Desktop Protocol client. 3 | Protocol services - Virtual channels 4 | Copyright 2003 Erik Forsberg for Cendio AB 5 | Copyright (C) Matthew Chapman 2003-2008 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | #define _CRT_SECURE_NO_WARNINGS 1 21 | #include "rdesktop.h" 22 | #include "util-xmalloc.h" 23 | #include "util-log.h" 24 | 25 | #include 26 | 27 | #define MAX_CHANNELS 6 28 | #define CHANNEL_CHUNK_LENGTH 1600 29 | #define CHANNEL_FLAG_FIRST 0x01 30 | #define CHANNEL_FLAG_LAST 0x02 31 | #define CHANNEL_FLAG_SHOW_PROTOCOL 0x10 32 | 33 | extern RDP_VERSION g_rdp_version; 34 | extern RD_BOOL g_encryption; 35 | 36 | VCHANNEL g_channels[MAX_CHANNELS]; 37 | unsigned int g_num_channels; 38 | 39 | /* FIXME: We should use the information in TAG_SRV_CHANNELS to map RDP5 40 | channels to MCS channels. 41 | 42 | The format of TAG_SRV_CHANNELS seems to be 43 | 44 | global_channel_no (uint16le) 45 | number_of_other_channels (uint16le) 46 | ..followed by uint16les for the other channels. 47 | */ 48 | 49 | VCHANNEL * 50 | channel_register(char *name, uint32 flags, void (*callback) (STREAM)) 51 | { 52 | VCHANNEL *channel; 53 | 54 | STATUS(8, "[+] register channel: \"%s\"\n", name); 55 | if (g_rdp_version < RDP_V5) 56 | return NULL; 57 | 58 | if (g_num_channels >= MAX_CHANNELS) 59 | { 60 | error("Channel table full, increase MAX_CHANNELS\n"); 61 | return NULL; 62 | } 63 | 64 | channel = &g_channels[g_num_channels]; 65 | channel->mcs_id = MCS_GLOBAL_CHANNEL + 1 + g_num_channels; 66 | strncpy(channel->name, name, 8); 67 | channel->flags = flags; 68 | channel->process = callback; 69 | g_num_channels++; 70 | return channel; 71 | } 72 | 73 | STREAM 74 | channel_init(VCHANNEL * channel, uint32 length) 75 | { 76 | STREAM s; 77 | 78 | s = sec_init(g_encryption ? SEC_ENCRYPT : 0, length + 8); 79 | s_push_layer(s, channel_hdr, 8); 80 | return s; 81 | } 82 | 83 | void 84 | channel_send(STREAM s, VCHANNEL * channel) 85 | { 86 | uint32 length, flags; 87 | uint32 thislength, remaining; 88 | uint8 *data; 89 | 90 | #ifdef WITH_SCARD 91 | scard_lock(SCARD_LOCK_CHANNEL); 92 | #endif 93 | 94 | /* first fragment sent in-place */ 95 | s_pop_layer(s, channel_hdr); 96 | length = (int)(s->end - s->p - 8); 97 | 98 | DEBUG_CHANNEL(("channel_send, length = %d\n", length)); 99 | 100 | thislength = MIN(length, CHANNEL_CHUNK_LENGTH); 101 | /* Note: In the original clipboard implementation, this number was 102 | 1592, not 1600. However, I don't remember the reason and 1600 seems 103 | to work so.. This applies only to *this* length, not the length of 104 | continuation or ending packets. */ 105 | remaining = length - thislength; 106 | flags = (remaining == 0) ? CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST : CHANNEL_FLAG_FIRST; 107 | if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL) 108 | flags |= CHANNEL_FLAG_SHOW_PROTOCOL; 109 | 110 | out_uint32_le(s, length); 111 | out_uint32_le(s, flags); 112 | data = s->end = s->p + thislength; 113 | DEBUG_CHANNEL(("Sending %d bytes with FLAG_FIRST\n", thislength)); 114 | sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id); 115 | 116 | /* subsequent segments copied (otherwise would have to generate headers backwards) */ 117 | while (remaining > 0) 118 | { 119 | thislength = MIN(remaining, CHANNEL_CHUNK_LENGTH); 120 | remaining -= thislength; 121 | flags = (remaining == 0) ? CHANNEL_FLAG_LAST : 0; 122 | if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL) 123 | flags |= CHANNEL_FLAG_SHOW_PROTOCOL; 124 | 125 | DEBUG_CHANNEL(("Sending %d bytes with flags %d\n", thislength, flags)); 126 | 127 | s = sec_init(g_encryption ? SEC_ENCRYPT : 0, thislength + 8); 128 | out_uint32_le(s, length); 129 | out_uint32_le(s, flags); 130 | out_uint8p(s, data, thislength); 131 | s_mark_end(s); 132 | sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id); 133 | 134 | data += thislength; 135 | } 136 | 137 | #ifdef WITH_SCARD 138 | scard_unlock(SCARD_LOCK_CHANNEL); 139 | #endif 140 | } 141 | 142 | void 143 | channel_process(STREAM s, uint16 mcs_channel) 144 | { 145 | uint32 length, flags; 146 | uint32 thislength; 147 | VCHANNEL *channel = NULL; 148 | unsigned int i; 149 | STREAM in; 150 | 151 | for (i = 0; i < g_num_channels; i++) 152 | { 153 | channel = &g_channels[i]; 154 | if (channel->mcs_id == mcs_channel) 155 | break; 156 | } 157 | 158 | if (i >= g_num_channels) 159 | return; 160 | 161 | in_uint32_le(s, length); 162 | in_uint32_le(s, flags); 163 | if ((flags & CHANNEL_FLAG_FIRST) && (flags & CHANNEL_FLAG_LAST)) 164 | { 165 | /* single fragment - pass straight up */ 166 | channel->process(s); 167 | } 168 | else 169 | { 170 | /* add fragment to defragmentation buffer */ 171 | in = &channel->in; 172 | if (flags & CHANNEL_FLAG_FIRST) 173 | { 174 | if (length > in->size) 175 | { 176 | in->data = (uint8 *) xrealloc(in->data, length); 177 | in->size = length; 178 | } 179 | in->p = in->data; 180 | } 181 | 182 | thislength = (int)MIN(s->end - s->p, in->data + in->size - in->p); 183 | memcpy(in->p, s->p, thislength); 184 | in->p += thislength; 185 | 186 | if (flags & CHANNEL_FLAG_LAST) 187 | { 188 | in->end = in->p; 189 | in->p = in->data; 190 | channel->process(in); 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /src/ranges6.h: -------------------------------------------------------------------------------- 1 | /* 2 | List of IPv6 ranges. 3 | 4 | Sames as the "ranges.h" module, but for IPv6 instead of IPv4. 5 | */ 6 | #ifndef RANGES6_H 7 | #define RANGES6_H 8 | #include 9 | #include 10 | 11 | typedef struct {uint64_t hi; uint64_t lo;} ipv6address; 12 | 13 | /** 14 | * A range of IPv6 ranges. 15 | * Inclusive, so [n..m] includes both 'n' and 'm'. 16 | */ 17 | struct Range6 18 | { 19 | ipv6address begin; 20 | ipv6address end; 21 | }; 22 | 23 | /** 24 | * An array of ranges in sorted order 25 | */ 26 | struct Range6List 27 | { 28 | struct Range6 *list; 29 | size_t count; 30 | size_t max; 31 | uint64_t *picker; 32 | }; 33 | 34 | /** 35 | * Adds the given range to the targets list. The given range can be a duplicate 36 | * or overlap with an existing range, which will get combined with existing 37 | * ranges. 38 | * @param targets 39 | * A list of IPv6 ranges. 40 | * @param begin 41 | * The first address of the range that'll be added. 42 | * @param end 43 | * The last address (inclusive) of the range that'll be added. 44 | */ 45 | void 46 | range6list_add_range(struct Range6List *targets, const ipv6address begin, const ipv6address end); 47 | 48 | /** 49 | * Removes the given range from the target list. The input range doesn't 50 | * have to exist, or can partial overlap with existing ranges. 51 | * @param targets 52 | * A list of IPv6 ranges. 53 | * @param begin 54 | * The first address of the range that'll be removed. 55 | * @param end 56 | * The last address of the range that'll be removed (inclusive). 57 | */ 58 | void 59 | range6list_remove_range(struct Range6List *targets, const ipv6address begin, const ipv6address end); 60 | 61 | /** 62 | * Same as 'rangelist_remove_range()', except the input is a range 63 | * structure instead of a start/stop numbers. 64 | */ 65 | void 66 | range6list_remove_range2(struct Range6List *targets, struct Range6 range); 67 | 68 | /** 69 | * Returns 'true' if the indicated IPv6 address is in one of the target 70 | * ranges. 71 | * @param targets 72 | * A list of IPv6 ranges 73 | * @param ip 74 | * An IPv6 address that might in be in the list of ranges 75 | * @return 76 | * 'true' if the ranges contain the item, or 'false' otherwise 77 | */ 78 | int 79 | range6list_is_contains(const struct Range6List *targets, const ipv6address ip); 80 | 81 | 82 | /** 83 | * Parses IPv6 addresses out of a string. A number of formats are allowed, 84 | * either an individual IPv6 address, a CIDR spec, or a start/stop address. 85 | * @param line 86 | * A line of text, probably read from a configuration file, or a string 87 | * probably input from the command line. It doesn't need to be nul 88 | * terminated. 89 | * @param inout_offset 90 | * The offset into the line were we are parsing. This integer will be 91 | * be incremented by the number of bytes we've parsed from the string. 92 | * @param max 93 | * The length of the line, in other words, the max value of inout_offset. 94 | */ 95 | struct Range6 96 | range6_parse(const char *line, unsigned *inout_offset, unsigned max); 97 | 98 | 99 | /** 100 | * Remove things from the target list. The primary use of this is the 101 | * "exclude-file" containing a list of IP addresses that we should 102 | * not scan 103 | * @param targets 104 | * Our array of target IP address (or port) ranges that we'll be 105 | * scanning. 106 | * @param excludes 107 | * A list, probably read in from --excludefile, of things that we 108 | * should not be scanning, that will override anything we otherwise 109 | * try to scan. 110 | * @return 111 | * the total number of IP addresses or ports removed. 112 | */ 113 | uint64_t 114 | range6list_exclude( struct Range6List *targets, 115 | const struct Range6List *excludes); 116 | 117 | 118 | /** 119 | * Counts the total number of IPv6 addresses in the target list. This 120 | * iterates over all the ranges in the table, summing up the count within 121 | * each range. 122 | * @param targets 123 | * A list of IP address or port ranges. 124 | * @return 125 | * The total number of address or ports. 126 | */ 127 | uint64_t 128 | range6list_count(const struct Range6List *targets); 129 | 130 | /** 131 | * Given an index in a continous range of [0...count], pick a corresponding 132 | * number (IP address or port) from a list of non-continuous ranges (not 133 | * necessarily starting from 0). In other words, given the two ranges 134 | * 10-19 50-69 135 | * we'll have a total of 30 possible numbers. Thus, the index goes from 136 | * [0..29], with the values 0..9 picking the corresponding values from the 137 | * first range, and the values 10..29 picking the corresponding values 138 | * from the second range. 139 | * 140 | * NOTE: This is a fundamental part of this program's design, that the user 141 | * can specify non-contiguous IP and port ranges, but yet we iterate over 142 | * them using a monotonicly increasing index variable. 143 | * 144 | * @param targets 145 | * A list of IP address ranges, or a list of port ranges (one or the 146 | * other, but not both). 147 | * @param index 148 | * An integer starting at 0 up to (but not including) the value returned 149 | * by 'rangelist_count()' for this target list. 150 | * @return 151 | * an IP address or port corresponding to this index. 152 | */ 153 | ipv6address 154 | range6list_pick(const struct Range6List *targets, uint64_t index); 155 | 156 | 157 | 158 | /** 159 | * Remove all the ranges in the range list. 160 | */ 161 | void 162 | range6list_remove_all(struct Range6List *list); 163 | 164 | /** 165 | * Merge two range lists 166 | */ 167 | void 168 | range6list_merge(struct Range6List *list1, const struct Range6List *list2); 169 | 170 | 171 | /** 172 | * Optimizes the target list, so that when we call "rangelist_pick()" 173 | * from an index, it runs faster. It currently configures this for 174 | * a binary-search, though in the future some more efficient 175 | * algorithm may be chosen. 176 | */ 177 | void 178 | range6list_optimize(struct Range6List *targets); 179 | 180 | /** 181 | * Does a regression test of this module 182 | * @return 183 | * 0 if the regression test succeeds, or a positive value on failure 184 | */ 185 | int 186 | ranges6_selftest(void); 187 | 188 | int 189 | my_aton6(const char *host, unsigned char *addr, size_t sizeof_addr); 190 | 191 | #endif 192 | -------------------------------------------------------------------------------- /src/ranges.h: -------------------------------------------------------------------------------- 1 | #ifndef RANGES_H 2 | #define RANGES_H 3 | #include 4 | #include 5 | 6 | /** 7 | * A range of either IP addresses or ports 8 | */ 9 | struct Range 10 | { 11 | unsigned begin; 12 | unsigned end; /* inclusive, so [n..m] includes both 'n' and 'm' */ 13 | }; 14 | 15 | /** 16 | * An array of ranges in sorted order 17 | */ 18 | struct RangeList 19 | { 20 | struct Range *list; 21 | unsigned count; 22 | unsigned max; 23 | unsigned *picker; 24 | unsigned *picker_hash; 25 | unsigned picker_mask; 26 | unsigned is_sorted:1; 27 | }; 28 | 29 | /** 30 | * Adds the given range to the task list. The given range can be a duplicate 31 | * or overlap with an existing range, which will get combined with existing 32 | * ranges. 33 | * @param task 34 | * A list of ranges of either IPv4 addresses or port numbers. 35 | * @param begin 36 | * The first address of the range that'll be added. 37 | * @param end 38 | * The last address (inclusive) of the range that'll be added. 39 | */ 40 | void 41 | rangelist_add_range(struct RangeList *task, unsigned begin, unsigned end); 42 | 43 | 44 | /** 45 | * Returns 'true' is the indicated port or IP address is in one of the task 46 | * ranges. 47 | * @param task 48 | * A list of ranges of either IPv4 addresses or port numbers. 49 | * @param number 50 | * Either an IPv4 address or a TCP/UDP port number. 51 | * @return 52 | * 'true' if the ranges contain the item, or 'false' otherwise 53 | */ 54 | int 55 | rangelist_is_contains(const struct RangeList *task, unsigned number); 56 | 57 | 58 | /** 59 | * Returns 'true' if the indicate range is valid, which is simple the 60 | * fact that 'begin' comes before 'end'. We mark invalid ranges 61 | * by putting 'begin' after the 'end' 62 | */ 63 | int 64 | range_is_valid(struct Range range); 65 | 66 | /** 67 | * Parses IPv4 addresses out of a string. A number of formats are allowed, 68 | * either an individual IPv4 address, a CIDR spec, or a start/stop address. 69 | * @param line 70 | * A line of text, probably read from a configuration file, or a string 71 | * probably input from the command line. It doesn't need to be nul 72 | * terminated. 73 | * @param inout_offset 74 | * The offset into the line were we are parsing. This integer will be 75 | * be incremented by the number of bytes we've parsed from the string. 76 | * @param max 77 | * The length of the line, in other words, the max value of inout_offset. 78 | */ 79 | struct Range 80 | range_parse_ipv4(const char *line, unsigned *inout_offset, unsigned max); 81 | 82 | 83 | /** 84 | * Remove things from the target list. The primary use of this is the 85 | * "exclude-file" containing a list of IP addresses that we should 86 | * not scan 87 | * @param targets 88 | * Our array of target IP address (or port) ranges that we'll be 89 | * scanning. 90 | * @param excludes 91 | * A list, probably read in from --excludefile, of things that we 92 | * should not be scanning, that will override anything we otherwise 93 | * try to scan. 94 | */ 95 | void 96 | rangelist_exclude( struct RangeList *targets, 97 | const struct RangeList *excludes); 98 | 99 | 100 | /** 101 | * Counts the total number of IP addresses or ports in the target list. This 102 | * iterates over all the ranges in the table, summing up the count within 103 | * each range. 104 | * @param targets 105 | * A list of IP address or port ranges. 106 | * @return 107 | * The total number of address or ports. 108 | */ 109 | uint64_t 110 | rangelist_count(const struct RangeList *targets); 111 | 112 | /** 113 | * Given an index in a continous range of [0...count], pick a corresponding 114 | * number (IP address or port) from a list of non-continuous ranges (not 115 | * necessarily starting from 0). In other words, given the two ranges 116 | * 10-19 50-69 117 | * we'll have a total of 30 possible numbers. Thus, the index goes from 118 | * [0..29], with the values 0..9 picking the corresponding values from the 119 | * first range, and the values 10..29 picking the corresponding values 120 | * from the second range. 121 | * 122 | * NOTE: This is a fundamental part of this program's design, that the user 123 | * can specify non-contiguous IP and port ranges, but yet we iterate over 124 | * them using a monotonicly increasing index variable. 125 | * 126 | * @param targets 127 | * A list of IP address ranges, or a list of port ranges (one or the 128 | * other, but not both). 129 | * @param index 130 | * An integer starting at 0 up to (but not including) the value returned 131 | * by 'rangelist_count()' for this target list. 132 | * @return 133 | * an IP address or port corresponding to this index. 134 | */ 135 | unsigned 136 | rangelist_pick(const struct RangeList *targets, uint64_t index); 137 | 138 | 139 | /** 140 | * Given a string like "80,8080,20-25,U:161", parse it into a structure 141 | * containing a list of port ranges. 142 | * 143 | * @param ports 144 | * The array of port ranges that's produced by this parsing function. 145 | * This structure will be used by the transmit thread when sending 146 | * probes to a target IP address. 147 | * @param string 148 | * A string from either the command-line or configuration file 149 | * in the nmap "ports" format. 150 | * @param is_error 151 | * Set to zero is no error occurred while parsing the string, or 152 | * set to a non-zero value if an error was found. 153 | * @return 154 | * the pointer in the string where the parsing ended, so that additional 155 | * things can be contained in the string, such as comments 156 | */ 157 | const char * 158 | rangelist_parse_ports( struct RangeList *ports, 159 | const char *string, 160 | unsigned *is_error, 161 | unsigned proto_offset 162 | ); 163 | 164 | 165 | /** 166 | * Remove all the ranges in the range list. 167 | */ 168 | void 169 | rangelist_remove_all(struct RangeList *list); 170 | 171 | /** 172 | * Merge two range lists 173 | */ 174 | void 175 | rangelist_merge(struct RangeList *list1, const struct RangeList *list2); 176 | 177 | 178 | /** 179 | * Optimizes the target list, so that when we call "rangelist_pick()" 180 | * from an index, it runs faster. It currently configures this for 181 | * a binary-search, though in the future some more efficient 182 | * algorithm may be chosen. 183 | */ 184 | void 185 | rangelist_optimize(struct RangeList *targets); 186 | 187 | 188 | /** 189 | * Sorts the list of target. We maintain the list of targets in sorted 190 | * order internally even though we scan the targets in random order 191 | * externally. 192 | */ 193 | void 194 | rangelist_sort(struct RangeList *targets); 195 | 196 | 197 | int 198 | my_aton4(const char *host, unsigned char *addr, size_t sizeof_addr); 199 | 200 | 201 | #endif 202 | -------------------------------------------------------------------------------- /src/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | rdesktop: A Remote Desktop Protocol client. 3 | Common data types 4 | Copyright (C) Matthew Chapman 1999-2008 5 | Copyright 2014 Henrik Andersson for Cendio AB 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | #ifndef RDESK_TYPES_H 21 | #define RDESK_TYPES_H 22 | #include "stream.h" 23 | #include "constants.h" 24 | #include 25 | #include 26 | #ifdef _WIN32 27 | typedef int DIR; 28 | #else 29 | #include 30 | #endif 31 | 32 | #ifndef PATH_MAX 33 | #define PATH_MAX 256 34 | #endif 35 | 36 | typedef int RD_BOOL; 37 | 38 | #ifndef True 39 | #define True (1) 40 | #define False (0) 41 | #endif 42 | 43 | typedef unsigned char uint8; 44 | typedef signed char sint8; 45 | typedef unsigned short uint16; 46 | typedef signed short sint16; 47 | typedef unsigned int uint32; 48 | typedef signed int sint32; 49 | 50 | typedef void *RD_HBITMAP; 51 | typedef void *RD_HGLYPH; 52 | typedef void *RD_HCOLOURMAP; 53 | typedef void *RD_HCURSOR; 54 | 55 | 56 | typedef enum _RDP_VERSION 57 | { 58 | RDP_V4 = 4, 59 | RDP_V5 = 5, 60 | RDP_V6 = 6 61 | } RDP_VERSION; 62 | 63 | 64 | typedef struct _RD_POINT 65 | { 66 | sint16 x, y; 67 | } 68 | RD_POINT; 69 | 70 | typedef struct _COLOURENTRY 71 | { 72 | uint8 red; 73 | uint8 green; 74 | uint8 blue; 75 | 76 | } 77 | COLOURENTRY; 78 | 79 | typedef struct _COLOURMAP 80 | { 81 | uint16 ncolours; 82 | COLOURENTRY *colours; 83 | 84 | } 85 | COLOURMAP; 86 | 87 | typedef struct _BOUNDS 88 | { 89 | sint16 left; 90 | sint16 top; 91 | sint16 right; 92 | sint16 bottom; 93 | 94 | } 95 | BOUNDS; 96 | 97 | typedef struct _PEN 98 | { 99 | uint8 style; 100 | uint8 width; 101 | uint32 colour; 102 | 103 | } 104 | PEN; 105 | 106 | /* this is whats in the brush cache */ 107 | typedef struct _BRUSHDATA 108 | { 109 | uint32 colour_code; 110 | uint32 data_size; 111 | uint8 *data; 112 | } 113 | BRUSHDATA; 114 | 115 | typedef struct _BRUSH 116 | { 117 | uint8 xorigin; 118 | uint8 yorigin; 119 | uint8 style; 120 | uint8 pattern[8]; 121 | BRUSHDATA *bd; 122 | } 123 | BRUSH; 124 | 125 | typedef struct _FONTGLYPH 126 | { 127 | sint16 offset; 128 | sint16 baseline; 129 | uint16 width; 130 | uint16 height; 131 | RD_HBITMAP pixmap; 132 | 133 | } 134 | FONTGLYPH; 135 | 136 | typedef struct _DATABLOB 137 | { 138 | void *data; 139 | int size; 140 | 141 | } 142 | DATABLOB; 143 | 144 | typedef struct _key_translation 145 | { 146 | /* For normal scancode translations */ 147 | uint8 scancode; 148 | uint16 modifiers; 149 | /* For sequences. If keysym is nonzero, the fields above are not used. */ 150 | uint32 seq_keysym; /* Really KeySym */ 151 | struct _key_translation *next; 152 | } 153 | key_translation; 154 | 155 | typedef struct _key_translation_entry 156 | { 157 | key_translation *tr; 158 | /* The full KeySym for this entry, not KEYMAP_MASKed */ 159 | uint32 keysym; 160 | /* This will be non-NULL if there has been a hash collision */ 161 | struct _key_translation_entry *next; 162 | } 163 | key_translation_entry; 164 | 165 | typedef struct _VCHANNEL 166 | { 167 | uint16 mcs_id; 168 | char name[8]; 169 | uint32 flags; 170 | struct stream in; 171 | void (*process) (STREAM); 172 | } 173 | VCHANNEL; 174 | 175 | /* PSTCACHE */ 176 | typedef uint8 HASH_KEY[8]; 177 | 178 | /* Header for an entry in the persistent bitmap cache file */ 179 | typedef struct _PSTCACHE_CELLHEADER 180 | { 181 | HASH_KEY key; 182 | uint8 width, height; 183 | uint16 length; 184 | uint32 stamp; 185 | } 186 | CELLHEADER; 187 | 188 | #define MAX_CBSIZE 256 189 | 190 | /* RDPSND */ 191 | typedef struct _RD_WAVEFORMATEX 192 | { 193 | uint16 wFormatTag; 194 | uint16 nChannels; 195 | uint32 nSamplesPerSec; 196 | uint32 nAvgBytesPerSec; 197 | uint16 nBlockAlign; 198 | uint16 wBitsPerSample; 199 | uint16 cbSize; 200 | uint8 cb[MAX_CBSIZE]; 201 | } RD_WAVEFORMATEX; 202 | 203 | typedef struct _RDPCOMP 204 | { 205 | uint32 roff; 206 | uint8 hist[RDP_MPPC_DICT_SIZE]; 207 | struct stream ns; 208 | } 209 | RDPCOMP; 210 | 211 | /* RDPDR */ 212 | typedef uint32 RD_NTSTATUS; 213 | typedef uint32 RD_NTHANDLE; 214 | 215 | typedef struct _DEVICE_FNS 216 | { 217 | RD_NTSTATUS(*create) (uint32 device, uint32 desired_access, uint32 share_mode, 218 | uint32 create_disposition, uint32 flags_and_attributes, 219 | char *filename, RD_NTHANDLE * handle); 220 | RD_NTSTATUS(*close) (RD_NTHANDLE handle); 221 | RD_NTSTATUS(*read) (RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, 222 | uint32 * result); 223 | RD_NTSTATUS(*write) (RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, 224 | uint32 * result); 225 | RD_NTSTATUS(*device_control) (RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out); 226 | } 227 | DEVICE_FNS; 228 | 229 | 230 | typedef struct rdpdr_device_info 231 | { 232 | uint32 device_type; 233 | RD_NTHANDLE handle; 234 | char name[8]; 235 | char *local_path; 236 | void *pdevice_data; 237 | } 238 | RDPDR_DEVICE; 239 | 240 | typedef struct rdpdr_serial_device_info 241 | { 242 | int dtr; 243 | int rts; 244 | uint32 control, xonoff, onlimit, offlimit; 245 | uint32 baud_rate, 246 | queue_in_size, 247 | queue_out_size, 248 | wait_mask, 249 | read_interval_timeout, 250 | read_total_timeout_multiplier, 251 | read_total_timeout_constant, 252 | write_total_timeout_multiplier, write_total_timeout_constant, posix_wait_mask; 253 | uint8 stop_bits, parity, word_length; 254 | uint8 chars[6]; 255 | struct termios *ptermios, *pold_termios; 256 | int event_txempty, event_cts, event_dsr, event_rlsd, event_pending; 257 | } 258 | SERIAL_DEVICE; 259 | 260 | typedef struct rdpdr_parallel_device_info 261 | { 262 | char *driver, *printer; 263 | uint32 queue_in_size, 264 | queue_out_size, 265 | wait_mask, 266 | read_interval_timeout, 267 | read_total_timeout_multiplier, 268 | read_total_timeout_constant, 269 | write_total_timeout_multiplier, 270 | write_total_timeout_constant, posix_wait_mask, bloblen; 271 | uint8 *blob; 272 | } 273 | PARALLEL_DEVICE; 274 | 275 | typedef struct rdpdr_printer_info 276 | { 277 | FILE *printer_fp; 278 | char *driver, *printer; 279 | uint32 bloblen; 280 | uint8 *blob; 281 | RD_BOOL default_printer; 282 | } 283 | PRINTER; 284 | 285 | typedef struct notify_data 286 | { 287 | time_t modify_time; 288 | time_t status_time; 289 | time_t total_time; 290 | unsigned int num_entries; 291 | } 292 | NOTIFY; 293 | 294 | 295 | typedef struct fileinfo 296 | { 297 | uint32 device_id, flags_and_attributes, accessmask; 298 | char path[PATH_MAX]; 299 | DIR *pdir; 300 | struct dirent *pdirent; 301 | char pattern[PATH_MAX]; 302 | RD_BOOL delete_on_close; 303 | NOTIFY notify; 304 | uint32 info_class; 305 | } 306 | FILEINFO; 307 | 308 | typedef RD_BOOL(*str_handle_lines_t) (const char *line, void *data); 309 | 310 | #endif 311 | 312 | -------------------------------------------------------------------------------- /src/ssl.c: -------------------------------------------------------------------------------- 1 | /* -*- c-basic-offset: 8 -*- 2 | rdesktop: A Remote Desktop Protocol client. 3 | Secure sockets abstraction layer 4 | Copyright (C) Matthew Chapman 1999-2008 5 | Copyright (C) Jay Sorg 2006-2008 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include "rdesktop.h" 22 | #include "ssl.h" 23 | #include "util-log.h" 24 | #include 25 | 26 | void 27 | rdssl_sha1_init(RDSSL_SHA1 * sha1) 28 | { 29 | SHA1_Init(sha1); 30 | } 31 | 32 | void 33 | rdssl_sha1_update(RDSSL_SHA1 * sha1, uint8 * data, uint32 len) 34 | { 35 | SHA1_Update(sha1, data, len); 36 | } 37 | 38 | void 39 | rdssl_sha1_final(RDSSL_SHA1 * sha1, uint8 * out_data) 40 | { 41 | SHA1_Final(out_data, sha1); 42 | } 43 | 44 | void 45 | rdssl_md5_init(RDSSL_MD5 * md5) 46 | { 47 | MD5_Init(md5); 48 | } 49 | 50 | void 51 | rdssl_md5_update(RDSSL_MD5 * md5, uint8 * data, uint32 len) 52 | { 53 | MD5_Update(md5, data, len); 54 | } 55 | 56 | void 57 | rdssl_md5_final(RDSSL_MD5 * md5, uint8 * out_data) 58 | { 59 | MD5_Final(out_data, md5); 60 | } 61 | 62 | void 63 | rdssl_rc4_set_key(RDSSL_RC4 * rc4, uint8 * key, uint32 len) 64 | { 65 | RC4_set_key(rc4, len, key); 66 | } 67 | 68 | void 69 | rdssl_rc4_crypt(RDSSL_RC4 * rc4, uint8 * in_data, uint8 * out_data, uint32 len) 70 | { 71 | RC4(rc4, len, in_data, out_data); 72 | } 73 | 74 | static void 75 | reverse(uint8 * p, int len) 76 | { 77 | int i, j; 78 | uint8 temp; 79 | 80 | for (i = 0, j = len - 1; i < j; i++, j--) 81 | { 82 | temp = p[i]; 83 | p[i] = p[j]; 84 | p[j] = temp; 85 | } 86 | } 87 | 88 | void 89 | rdssl_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus, 90 | uint8 * exponent) 91 | { 92 | BN_CTX *ctx; 93 | BIGNUM *mod, *exp, *x, *y; 94 | uint8 inr[SEC_MAX_MODULUS_SIZE]; 95 | int outlen; 96 | 97 | reverse(modulus, modulus_size); 98 | reverse(exponent, SEC_EXPONENT_SIZE); 99 | memcpy(inr, in, len); 100 | reverse(inr, len); 101 | 102 | ctx = BN_CTX_new(); 103 | mod = BN_new(); 104 | exp = BN_new(); 105 | x = BN_new(); 106 | y = BN_new(); 107 | 108 | BN_bin2bn(modulus, modulus_size, mod); 109 | BN_bin2bn(exponent, SEC_EXPONENT_SIZE, exp); 110 | BN_bin2bn(inr, len, x); 111 | BN_mod_exp(y, x, exp, mod, ctx); 112 | outlen = BN_bn2bin(y, out); 113 | reverse(out, outlen); 114 | if (outlen < (int) modulus_size) 115 | memset(out + outlen, 0, modulus_size - outlen); 116 | 117 | BN_free(y); 118 | BN_clear_free(x); 119 | BN_free(exp); 120 | BN_free(mod); 121 | BN_CTX_free(ctx); 122 | } 123 | 124 | /* returns newly allocated RDSSL_CERT or NULL */ 125 | RDSSL_CERT * 126 | rdssl_cert_read(uint8 * data, uint32 len) 127 | { 128 | /* this will move the data pointer but we don't care, we don't use it again */ 129 | return d2i_X509(NULL, (D2I_X509_CONST unsigned char **) &data, len); 130 | } 131 | 132 | void 133 | rdssl_cert_free(RDSSL_CERT * cert) 134 | { 135 | X509_free(cert); 136 | } 137 | 138 | /* returns newly allocated RDSSL_RKEY or NULL */ 139 | RDSSL_RKEY * 140 | rdssl_cert_to_rkey(RDSSL_CERT * cert, uint32 * key_len) 141 | { 142 | EVP_PKEY *epk = NULL; 143 | RDSSL_RKEY *lkey; 144 | int nid; 145 | 146 | /* By some reason, Microsoft sets the OID of the Public RSA key to 147 | the oid for "MD5 with RSA Encryption" instead of "RSA Encryption" 148 | 149 | Kudos to Richard Levitte for the following (. intiutive .) 150 | lines of code that resets the OID and let's us extract the key. */ 151 | 152 | X509_PUBKEY *key = NULL; 153 | X509_ALGOR *algor = NULL; 154 | 155 | /* First, log the subject name, so we know more about the target 156 | * that we are scanning */ 157 | { 158 | char *name = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); 159 | if (name == NULL) { 160 | STATUS(0, "RDPsec - can't get certificate subject name\n"); 161 | } else { 162 | STATUS(1, "subject = %s\n", name); 163 | OPENSSL_free(name); 164 | } 165 | } 166 | key = X509_get_X509_PUBKEY(cert); 167 | 168 | /* (Rob) It looks like this code can't work, as the return type 169 | * is wrong. FIXME TODO */ 170 | X509_PUBKEY_get0_param(NULL, NULL, 0, &algor, key); 171 | 172 | nid = OBJ_obj2nid(algor->algorithm); 173 | 174 | if ((nid == NID_md5WithRSAEncryption) || (nid == NID_shaWithRSAEncryption)) 175 | { 176 | DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n")); 177 | X509_PUBKEY_set0_param(key, OBJ_nid2obj(NID_rsaEncryption), 178 | 0, NULL, NULL, 0); 179 | } 180 | epk = X509_get_pubkey(cert); 181 | if (NULL == epk) 182 | { 183 | STATUS(1, "Failed to extract public key from certificate\n"); 184 | RESULT("UNKNOWN - RDP protocol error - failed to extract public-key\n"); 185 | return NULL; 186 | } 187 | 188 | lkey = RSAPublicKey_dup(EVP_PKEY_get1_RSA(epk)); 189 | EVP_PKEY_free(epk); 190 | *key_len = RSA_size(lkey); 191 | return lkey; 192 | } 193 | 194 | /* returns boolean */ 195 | RD_BOOL 196 | rdssl_certs_ok(RDSSL_CERT * server_cert, RDSSL_CERT * cacert) 197 | { 198 | /* Currently, we don't use the CA Certificate. 199 | FIXME: 200 | *) Verify the server certificate (server_cert) with the 201 | CA certificate. 202 | *) Store the CA Certificate with the hostname of the 203 | server we are connecting to as key, and compare it 204 | when we connect the next time, in order to prevent 205 | MITM-attacks. 206 | */ 207 | return True; 208 | } 209 | 210 | int 211 | rdssl_cert_print_fp(FILE * fp, RDSSL_CERT * cert) 212 | { 213 | return X509_print_fp(fp, cert); 214 | } 215 | 216 | void 217 | rdssl_rkey_free(RDSSL_RKEY * rkey) 218 | { 219 | RSA_free(rkey); 220 | } 221 | 222 | /* returns error */ 223 | int 224 | rdssl_rkey_get_exp_mod(RDSSL_RKEY * rkey, uint8 * exponent, uint32 max_exp_len, uint8 * modulus, 225 | uint32 max_mod_len) 226 | { 227 | int len; 228 | 229 | const BIGNUM *e = NULL; 230 | const BIGNUM *n = NULL; 231 | 232 | #if OPENSSL_VERSION_NUMBER < 0x10100000L 233 | e = rkey->e; 234 | n = rkey->n; 235 | #else 236 | RSA_get0_key(rkey, &e, &n, NULL); 237 | #endif 238 | 239 | if ((BN_num_bytes(e) > (int) max_exp_len) || 240 | (BN_num_bytes(n) > (int) max_mod_len)) 241 | { 242 | return 1; 243 | } 244 | len = BN_bn2bin(e, exponent); 245 | reverse(exponent, len); 246 | len = BN_bn2bin(n, modulus); 247 | reverse(modulus, len); 248 | return 0; 249 | } 250 | 251 | /* returns boolean */ 252 | RD_BOOL 253 | rdssl_sig_ok(uint8 * exponent, uint32 exp_len, uint8 * modulus, uint32 mod_len, 254 | uint8 * signature, uint32 sig_len) 255 | { 256 | /* Currently, we don't check the signature 257 | FIXME: 258 | */ 259 | return True; 260 | } 261 | 262 | 263 | void 264 | rdssl_hmac_md5(const void *key, int key_len, const unsigned char *msg, int msg_len, 265 | unsigned char *md) 266 | { 267 | HMAC(EVP_md5(), key, key_len, msg, msg_len, md, NULL); 268 | } 269 | -------------------------------------------------------------------------------- /src/orders.h: -------------------------------------------------------------------------------- 1 | /* 2 | rdesktop: A Remote Desktop Protocol client. 3 | RDP order processing 4 | Copyright (C) Matthew Chapman 1999-2008 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #define RDP_ORDER_STANDARD 0x01 21 | #define RDP_ORDER_SECONDARY 0x02 22 | #define RDP_ORDER_BOUNDS 0x04 23 | #define RDP_ORDER_CHANGE 0x08 24 | #define RDP_ORDER_DELTA 0x10 25 | #define RDP_ORDER_LASTBOUNDS 0x20 26 | #define RDP_ORDER_SMALL 0x40 27 | #define RDP_ORDER_TINY 0x80 28 | 29 | enum RDP_ORDER_TYPE 30 | { 31 | RDP_ORDER_DESTBLT = 0, 32 | RDP_ORDER_PATBLT = 1, 33 | RDP_ORDER_SCREENBLT = 2, 34 | RDP_ORDER_LINE = 9, 35 | RDP_ORDER_RECT = 10, 36 | RDP_ORDER_DESKSAVE = 11, 37 | RDP_ORDER_MEMBLT = 13, 38 | RDP_ORDER_TRIBLT = 14, 39 | RDP_ORDER_POLYGON = 20, 40 | RDP_ORDER_POLYGON2 = 21, 41 | RDP_ORDER_POLYLINE = 22, 42 | RDP_ORDER_ELLIPSE = 25, 43 | RDP_ORDER_ELLIPSE2 = 26, 44 | RDP_ORDER_TEXT2 = 27 45 | }; 46 | 47 | enum RDP_SECONDARY_ORDER_TYPE 48 | { 49 | RDP_ORDER_RAW_BMPCACHE = 0, 50 | RDP_ORDER_COLCACHE = 1, 51 | RDP_ORDER_BMPCACHE = 2, 52 | RDP_ORDER_FONTCACHE = 3, 53 | RDP_ORDER_RAW_BMPCACHE2 = 4, 54 | RDP_ORDER_BMPCACHE2 = 5, 55 | RDP_ORDER_BRUSHCACHE = 7 56 | }; 57 | 58 | typedef struct _DESTBLT_ORDER 59 | { 60 | sint16 x; 61 | sint16 y; 62 | sint16 cx; 63 | sint16 cy; 64 | uint8 opcode; 65 | 66 | } 67 | DESTBLT_ORDER; 68 | 69 | typedef struct _PATBLT_ORDER 70 | { 71 | sint16 x; 72 | sint16 y; 73 | sint16 cx; 74 | sint16 cy; 75 | uint8 opcode; 76 | uint32 bgcolour; 77 | uint32 fgcolour; 78 | BRUSH brush; 79 | 80 | } 81 | PATBLT_ORDER; 82 | 83 | typedef struct _SCREENBLT_ORDER 84 | { 85 | sint16 x; 86 | sint16 y; 87 | sint16 cx; 88 | sint16 cy; 89 | uint8 opcode; 90 | sint16 srcx; 91 | sint16 srcy; 92 | 93 | } 94 | SCREENBLT_ORDER; 95 | 96 | typedef struct _LINE_ORDER 97 | { 98 | uint16 mixmode; 99 | sint16 startx; 100 | sint16 starty; 101 | sint16 endx; 102 | sint16 endy; 103 | uint32 bgcolour; 104 | uint8 opcode; 105 | PEN pen; 106 | 107 | } 108 | LINE_ORDER; 109 | 110 | typedef struct _RECT_ORDER 111 | { 112 | sint16 x; 113 | sint16 y; 114 | sint16 cx; 115 | sint16 cy; 116 | uint32 colour; 117 | 118 | } 119 | RECT_ORDER; 120 | 121 | typedef struct _DESKSAVE_ORDER 122 | { 123 | uint32 offset; 124 | sint16 left; 125 | sint16 top; 126 | sint16 right; 127 | sint16 bottom; 128 | uint8 action; 129 | 130 | } 131 | DESKSAVE_ORDER; 132 | 133 | typedef struct _TRIBLT_ORDER 134 | { 135 | uint8 colour_table; 136 | uint8 cache_id; 137 | sint16 x; 138 | sint16 y; 139 | sint16 cx; 140 | sint16 cy; 141 | uint8 opcode; 142 | sint16 srcx; 143 | sint16 srcy; 144 | uint32 bgcolour; 145 | uint32 fgcolour; 146 | BRUSH brush; 147 | uint16 cache_idx; 148 | uint16 unknown; 149 | 150 | } 151 | TRIBLT_ORDER; 152 | 153 | typedef struct _MEMBLT_ORDER 154 | { 155 | uint8 colour_table; 156 | uint8 cache_id; 157 | sint16 x; 158 | sint16 y; 159 | sint16 cx; 160 | sint16 cy; 161 | uint8 opcode; 162 | sint16 srcx; 163 | sint16 srcy; 164 | uint16 cache_idx; 165 | 166 | } 167 | MEMBLT_ORDER; 168 | 169 | #define MAX_DATA 256 170 | 171 | typedef struct _POLYGON_ORDER 172 | { 173 | sint16 x; 174 | sint16 y; 175 | uint8 opcode; 176 | uint8 fillmode; 177 | uint32 fgcolour; 178 | uint8 npoints; 179 | uint8 datasize; 180 | uint8 data[MAX_DATA]; 181 | 182 | } 183 | POLYGON_ORDER; 184 | 185 | typedef struct _POLYGON2_ORDER 186 | { 187 | sint16 x; 188 | sint16 y; 189 | uint8 opcode; 190 | uint8 fillmode; 191 | uint32 bgcolour; 192 | uint32 fgcolour; 193 | BRUSH brush; 194 | uint8 npoints; 195 | uint8 datasize; 196 | uint8 data[MAX_DATA]; 197 | 198 | } 199 | POLYGON2_ORDER; 200 | 201 | typedef struct _POLYLINE_ORDER 202 | { 203 | sint16 x; 204 | sint16 y; 205 | uint8 opcode; 206 | uint32 fgcolour; 207 | uint8 lines; 208 | uint8 datasize; 209 | uint8 data[MAX_DATA]; 210 | 211 | } 212 | POLYLINE_ORDER; 213 | 214 | typedef struct _ELLIPSE_ORDER 215 | { 216 | sint16 left; 217 | sint16 top; 218 | sint16 right; 219 | sint16 bottom; 220 | uint8 opcode; 221 | uint8 fillmode; 222 | uint32 fgcolour; 223 | 224 | } 225 | ELLIPSE_ORDER; 226 | 227 | typedef struct _ELLIPSE2_ORDER 228 | { 229 | sint16 left; 230 | sint16 top; 231 | sint16 right; 232 | sint16 bottom; 233 | uint8 opcode; 234 | uint8 fillmode; 235 | BRUSH brush; 236 | uint32 bgcolour; 237 | uint32 fgcolour; 238 | 239 | } 240 | ELLIPSE2_ORDER; 241 | 242 | #define MAX_TEXT 256 243 | 244 | typedef struct _TEXT2_ORDER 245 | { 246 | uint8 font; 247 | uint8 flags; 248 | uint8 opcode; 249 | uint8 mixmode; 250 | uint32 bgcolour; 251 | uint32 fgcolour; 252 | sint16 clipleft; 253 | sint16 cliptop; 254 | sint16 clipright; 255 | sint16 clipbottom; 256 | sint16 boxleft; 257 | sint16 boxtop; 258 | sint16 boxright; 259 | sint16 boxbottom; 260 | BRUSH brush; 261 | sint16 x; 262 | sint16 y; 263 | uint8 length; 264 | uint8 text[MAX_TEXT]; 265 | 266 | } 267 | TEXT2_ORDER; 268 | 269 | typedef struct _RDP_ORDER_STATE 270 | { 271 | uint8 order_type; 272 | BOUNDS bounds; 273 | 274 | DESTBLT_ORDER destblt; 275 | PATBLT_ORDER patblt; 276 | SCREENBLT_ORDER screenblt; 277 | LINE_ORDER line; 278 | RECT_ORDER rect; 279 | DESKSAVE_ORDER desksave; 280 | MEMBLT_ORDER memblt; 281 | TRIBLT_ORDER triblt; 282 | POLYGON_ORDER polygon; 283 | POLYGON2_ORDER polygon2; 284 | POLYLINE_ORDER polyline; 285 | ELLIPSE_ORDER ellipse; 286 | ELLIPSE2_ORDER ellipse2; 287 | TEXT2_ORDER text2; 288 | 289 | } 290 | RDP_ORDER_STATE; 291 | 292 | typedef struct _RDP_RAW_BMPCACHE_ORDER 293 | { 294 | uint8 cache_id; 295 | uint8 pad1; 296 | uint8 width; 297 | uint8 height; 298 | uint8 bpp; 299 | uint16 bufsize; 300 | uint16 cache_idx; 301 | uint8 *data; 302 | 303 | } 304 | RDP_RAW_BMPCACHE_ORDER; 305 | 306 | typedef struct _RDP_BMPCACHE_ORDER 307 | { 308 | uint8 cache_id; 309 | uint8 pad1; 310 | uint8 width; 311 | uint8 height; 312 | uint8 bpp; 313 | uint16 bufsize; 314 | uint16 cache_idx; 315 | uint16 pad2; 316 | uint16 size; 317 | uint16 row_size; 318 | uint16 final_size; 319 | uint8 *data; 320 | 321 | } 322 | RDP_BMPCACHE_ORDER; 323 | 324 | /* RDP_BMPCACHE2_ORDER */ 325 | #define ID_MASK 0x0007 326 | #define MODE_MASK 0x0038 327 | #define SQUARE 0x0080 328 | #define PERSIST 0x0100 329 | #define FLAG_51_UNKNOWN 0x0800 330 | 331 | #define MODE_SHIFT 3 332 | 333 | #define LONG_FORMAT 0x80 334 | #define BUFSIZE_MASK 0x3FFF /* or 0x1FFF? */ 335 | 336 | #define MAX_GLYPH 32 337 | 338 | typedef struct _RDP_FONT_GLYPH 339 | { 340 | uint16 character; 341 | uint16 unknown; 342 | uint16 baseline; 343 | uint16 width; 344 | uint16 height; 345 | uint8 data[MAX_GLYPH]; 346 | 347 | } 348 | RDP_FONT_GLYPH; 349 | 350 | #define MAX_GLYPHS 256 351 | 352 | typedef struct _RDP_FONTCACHE_ORDER 353 | { 354 | uint8 font; 355 | uint8 nglyphs; 356 | RDP_FONT_GLYPH glyphs[MAX_GLYPHS]; 357 | 358 | } 359 | RDP_FONTCACHE_ORDER; 360 | 361 | typedef struct _RDP_COLCACHE_ORDER 362 | { 363 | uint8 cache_id; 364 | COLOURMAP map; 365 | 366 | } 367 | RDP_COLCACHE_ORDER; 368 | -------------------------------------------------------------------------------- /src/proto.h: -------------------------------------------------------------------------------- 1 | /* -*- c-basic-offset: 8 -*- 2 | rdesktop: A Remote Desktop Protocol client. 3 | Copyright (C) Matthew Chapman 1999-2008 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RDESKTOP_PROTO_H 20 | #define RDESKTOP_PROTO_H 21 | 22 | /* *INDENT-OFF* */ 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | /* *INDENT-ON* */ 27 | 28 | /* channels.c */ 29 | VCHANNEL *channel_register(char *name, uint32 flags, void (*callback) (STREAM)); 30 | STREAM channel_init(VCHANNEL * channel, uint32 length); 31 | void channel_send(STREAM s, VCHANNEL * channel); 32 | void channel_process(STREAM s, uint16 mcs_channel); 33 | /* cliprdr.c */ 34 | void cliprdr_send_simple_native_format_announce(uint32 format); 35 | void cliprdr_send_native_format_announce(uint8 * formats_data, uint32 formats_data_length); 36 | void cliprdr_send_data_request(uint32 format); 37 | void cliprdr_send_data(uint8 * data, uint32 length); 38 | void cliprdr_set_mode(const char *optarg); 39 | RD_BOOL cliprdr_init(void); 40 | /* ctrl.c */ 41 | int ctrl_init(const char *user, const char *domain, const char *host); 42 | void ctrl_cleanup(void); 43 | RD_BOOL ctrl_is_slave(void); 44 | int ctrl_send_command(const char *cmd, const char *args); 45 | //void ctrl_add_fds(int *n, fd_set * rfds); 46 | //void ctrl_check_fds(fd_set * rfds, fd_set * wfds); 47 | 48 | /* disk.c */ 49 | int disk_enum_devices(uint32 * id, char *optarg); 50 | RD_NTSTATUS disk_query_information(RD_NTHANDLE handle, uint32 info_class, STREAM out); 51 | RD_NTSTATUS disk_set_information(RD_NTHANDLE handle, uint32 info_class, STREAM in, STREAM out); 52 | RD_NTSTATUS disk_check_notify(RD_NTHANDLE handle); 53 | RD_NTSTATUS disk_create_notify(RD_NTHANDLE handle, uint32 info_class); 54 | RD_NTSTATUS disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out); 55 | RD_NTSTATUS disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREAM out); 56 | /* mppc.c */ 57 | int mppc_expand(uint8 * data, uint32 clen, uint8 ctype, uint32 * roff, uint32 * rlen); 58 | /* ewmhints.c */ 59 | int get_current_workarea(uint32 * x, uint32 * y, uint32 * width, uint32 * height); 60 | void ewmh_init(void); 61 | /* iso.c */ 62 | STREAM iso_init(int length); 63 | void iso_send(STREAM s); 64 | STREAM iso_recv(uint8 * rdpver); 65 | RD_BOOL iso_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect, 66 | uint32 * selected_protocol); 67 | void iso_disconnect(void); 68 | void iso_reset_state(void); 69 | /* cssp.c */ 70 | RD_BOOL cssp_connect(char *server, char *user, char *domain, char *password, STREAM s); 71 | /* licence.c */ 72 | void licence_process(STREAM s); 73 | /* mcs.c */ 74 | STREAM mcs_init(int length); 75 | void mcs_send_to_channel(STREAM s, uint16 channel); 76 | void mcs_send(STREAM s); 77 | STREAM mcs_recv(uint16 * channel, uint8 * rdpver); 78 | RD_BOOL mcs_connect_start(char *server, char *username, char *domain, char *password, 79 | RD_BOOL reconnect, uint32 * selected_protocol); 80 | RD_BOOL mcs_connect_finalize(STREAM s); 81 | void mcs_disconnect(void); 82 | void mcs_reset_state(void); 83 | /* orders.c */ 84 | void process_orders(STREAM s, uint16 num_orders); 85 | void reset_order_state(void); 86 | /* parallel.c */ 87 | int parallel_enum_devices(uint32 * id, char *optarg); 88 | /* printer.c */ 89 | int printer_enum_devices(uint32 * id, char *optarg); 90 | /* printercache.c */ 91 | int printercache_load_blob(char *printer_name, uint8 ** data); 92 | void printercache_process(STREAM s); 93 | /* pstcache.c */ 94 | void pstcache_touch_bitmap(uint8 cache_id, uint16 cache_idx, uint32 stamp); 95 | RD_BOOL pstcache_load_bitmap(uint8 cache_id, uint16 cache_idx); 96 | RD_BOOL pstcache_save_bitmap(uint8 cache_id, uint16 cache_idx, uint8 * key, uint8 width, 97 | uint8 height, uint16 length, uint8 * data); 98 | int pstcache_enumerate(uint8 id, HASH_KEY * keylist); 99 | RD_BOOL pstcache_init(uint8 cache_id); 100 | /* rdesktop.c */ 101 | 102 | //char *next_arg(char *src, char needle); 103 | void toupper_str(char *p); 104 | RD_BOOL str_startswith(const char *s, const char *prefix); 105 | RD_BOOL str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler, 106 | void *data); 107 | RD_BOOL subprocess(char *const argv[], str_handle_lines_t linehandler, void *data); 108 | char *l_to_a(long N, int base); 109 | int load_licence(unsigned char **data); 110 | void save_licence(unsigned char *data, int length); 111 | void rd_create_ui(void); 112 | RD_BOOL rd_pstcache_mkdir(void); 113 | int rd_open_file(char *filename); 114 | void rd_close_file(int fd); 115 | int rd_read_file(int fd, void *ptr, int len); 116 | int rd_write_file(int fd, void *ptr, int len); 117 | int rd_lseek_file(int fd, int offset); 118 | RD_BOOL rd_lock_file(int fd, int start, int len); 119 | /* rdp5.c */ 120 | void rdp5_process(STREAM s); 121 | /* rdp.c */ 122 | void rdp_out_unistr(STREAM s, char *string, int len); 123 | void rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size); 124 | void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, 125 | uint16 param2); 126 | void rdp_send_client_window_status(int status); 127 | void process_colour_pointer_pdu(STREAM s); 128 | void process_new_pointer_pdu(STREAM s); 129 | void process_cached_pointer_pdu(STREAM s); 130 | void process_system_pointer_pdu(STREAM s); 131 | void process_bitmap_updates(STREAM s); 132 | void process_palette(STREAM s); 133 | void process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason); 134 | void rdp_main_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason); 135 | RD_BOOL rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason); 136 | RD_BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, char *command, 137 | char *directory, RD_BOOL reconnect); 138 | void rdp_reset_state(void); 139 | void rdp_disconnect(void); 140 | /* rdpdr.c */ 141 | int get_device_index(RD_NTHANDLE handle); 142 | void convert_to_unix_filename(char *filename); 143 | void rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer, 144 | uint32 length); 145 | RD_BOOL rdpdr_init(void); 146 | //void rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, RD_BOOL * timeout); 147 | struct async_iorequest *rdpdr_remove_iorequest(struct async_iorequest *prev, 148 | struct async_iorequest *iorq); 149 | //void rdpdr_check_fds(fd_set * rfds, fd_set * wfds, RD_BOOL timed_out); 150 | RD_BOOL rdpdr_abort_io(uint32 fd, uint32 major, RD_NTSTATUS status); 151 | /* rdpsnd.c */ 152 | void rdpsnd_record(const void *data, unsigned int size); 153 | RD_BOOL rdpsnd_init(char *optarg); 154 | void rdpsnd_show_help(void); 155 | //void rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv); 156 | //void rdpsnd_check_fds(fd_set * rfds, fd_set * wfds); 157 | struct audio_packet *rdpsnd_queue_current_packet(void); 158 | RD_BOOL rdpsnd_queue_empty(void); 159 | void rdpsnd_queue_next(unsigned long completed_in_us); 160 | int rdpsnd_queue_next_tick(void); 161 | void rdpsnd_reset_state(void); 162 | /* secure.c */ 163 | void sec_hash_to_string(char *out, int out_size, uint8 * in, int in_size); 164 | void sec_hash_sha1_16(uint8 * out, uint8 * in, uint8 * salt1); 165 | void sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt); 166 | void sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2); 167 | void buf_out_uint32(uint8 * buffer, uint32 value); 168 | void sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, 169 | int datalen); 170 | void sec_decrypt(uint8 * data, int length); 171 | STREAM sec_init(uint32 flags, int maxlen); 172 | void sec_send_to_channel(STREAM s, uint32 flags, uint16 channel); 173 | void sec_send(STREAM s, uint32 flags); 174 | void sec_process_mcs_data(STREAM s); 175 | STREAM sec_recv(uint8 * rdpver); 176 | RD_BOOL sec_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect); 177 | void sec_disconnect(void); 178 | void sec_reset_state(void); 179 | /* serial.c */ 180 | int serial_enum_devices(uint32 * id, char *optarg); 181 | RD_BOOL serial_get_event(RD_NTHANDLE handle, uint32 * result); 182 | RD_BOOL serial_get_timeout(RD_NTHANDLE handle, uint32 length, uint32 * timeout, 183 | uint32 * itv_timeout); 184 | 185 | 186 | 187 | 188 | /* *INDENT-OFF* */ 189 | #ifdef __cplusplus 190 | } 191 | #endif 192 | /* *INDENT-ON* */ 193 | 194 | #endif 195 | -------------------------------------------------------------------------------- /src/mcs.c: -------------------------------------------------------------------------------- 1 | /* -*- c-basic-offset: 8 -*- 2 | rdesktop: A Remote Desktop Protocol client. 3 | Protocol services - Multipoint Communications Service 4 | Copyright (C) Matthew Chapman 1999-2008 5 | Copyright 2005-2011 Peter Astrand for Cendio AB 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include "rdesktop.h" 22 | #include "asn.h" 23 | #include "util-log.h" 24 | #include 25 | #include 26 | 27 | uint16 g_mcs_userid; 28 | extern VCHANNEL g_channels[]; 29 | extern unsigned int g_num_channels; 30 | 31 | 32 | /* Output a DOMAIN_PARAMS structure (ASN.1 BER) */ 33 | static void 34 | mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize) 35 | { 36 | ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 32); 37 | ber_out_integer(s, max_channels); 38 | ber_out_integer(s, max_users); 39 | ber_out_integer(s, max_tokens); 40 | ber_out_integer(s, 1); /* num_priorities */ 41 | ber_out_integer(s, 0); /* min_throughput */ 42 | ber_out_integer(s, 1); /* max_height */ 43 | ber_out_integer(s, max_pdusize); 44 | ber_out_integer(s, 2); /* ver_protocol */ 45 | } 46 | 47 | /* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */ 48 | static RD_BOOL 49 | mcs_parse_domain_params(STREAM s) 50 | { 51 | int length; 52 | 53 | ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length); 54 | in_uint8s(s, length); 55 | 56 | return s_check(s); 57 | } 58 | 59 | /* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */ 60 | static void 61 | mcs_send_connect_initial(STREAM mcs_data) 62 | { 63 | int datalen = (int)(mcs_data->end - mcs_data->data); 64 | int length = 9 + 3 * 34 + 4 + datalen; 65 | STREAM s; 66 | 67 | s = iso_init(length + 5); 68 | 69 | ber_out_header(s, MCS_CONNECT_INITIAL, length); 70 | ber_out_header(s, BER_TAG_OCTET_STRING, 1); /* calling domain */ 71 | out_uint8(s, 1); 72 | ber_out_header(s, BER_TAG_OCTET_STRING, 1); /* called domain */ 73 | out_uint8(s, 1); 74 | 75 | ber_out_header(s, BER_TAG_BOOLEAN, 1); 76 | out_uint8(s, 0xff); /* upward flag */ 77 | 78 | mcs_out_domain_params(s, 34, 2, 0, 0xffff); /* target params */ 79 | mcs_out_domain_params(s, 1, 1, 1, 0x420); /* min params */ 80 | mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff); /* max params */ 81 | 82 | ber_out_header(s, BER_TAG_OCTET_STRING, datalen); 83 | out_uint8p(s, mcs_data->data, datalen); 84 | 85 | s_mark_end(s); 86 | iso_send(s); 87 | } 88 | 89 | /* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */ 90 | static RD_BOOL 91 | mcs_recv_connect_response(STREAM mcs_data) 92 | { 93 | uint8 result; 94 | int length; 95 | STREAM s; 96 | 97 | s = iso_recv(NULL); 98 | if (s == NULL) 99 | return False; 100 | 101 | ber_parse_header(s, MCS_CONNECT_RESPONSE, &length); 102 | 103 | ber_parse_header(s, BER_TAG_RESULT, &length); 104 | in_uint8(s, result); 105 | if (result != 0) 106 | { 107 | error("MCS connect: %d\n", result); 108 | return False; 109 | } 110 | 111 | ber_parse_header(s, BER_TAG_INTEGER, &length); 112 | in_uint8s(s, length); /* connect id */ 113 | mcs_parse_domain_params(s); 114 | 115 | ber_parse_header(s, BER_TAG_OCTET_STRING, &length); 116 | 117 | sec_process_mcs_data(s); 118 | /* 119 | if (length > mcs_data->size) 120 | { 121 | error("MCS data length %d, expected %d\n", length, 122 | mcs_data->size); 123 | length = mcs_data->size; 124 | } 125 | 126 | in_uint8a(s, mcs_data->data, length); 127 | mcs_data->p = mcs_data->data; 128 | mcs_data->end = mcs_data->data + length; 129 | */ 130 | return s_check_end(s); 131 | } 132 | 133 | /* Send an EDrq message (ASN.1 PER) */ 134 | static void 135 | mcs_send_edrq(void) 136 | { 137 | STREAM s; 138 | 139 | s = iso_init(5); 140 | 141 | out_uint8(s, (MCS_EDRQ << 2)); 142 | out_uint16_be(s, 1); /* height */ 143 | out_uint16_be(s, 1); /* interval */ 144 | 145 | s_mark_end(s); 146 | iso_send(s); 147 | } 148 | 149 | /* Send an AUrq message (ASN.1 PER) */ 150 | static void 151 | mcs_send_aurq(void) 152 | { 153 | STREAM s; 154 | 155 | s = iso_init(1); 156 | 157 | out_uint8(s, (MCS_AURQ << 2)); 158 | 159 | s_mark_end(s); 160 | iso_send(s); 161 | } 162 | 163 | /* Expect a AUcf message (ASN.1 PER) */ 164 | static RD_BOOL 165 | mcs_recv_aucf(uint16 * mcs_userid) 166 | { 167 | uint8 opcode, result; 168 | STREAM s; 169 | 170 | s = iso_recv(NULL); 171 | if (s == NULL) 172 | return False; 173 | 174 | in_uint8(s, opcode); 175 | if ((opcode >> 2) != MCS_AUCF) 176 | { 177 | error("expected AUcf, got %d\n", opcode); 178 | return False; 179 | } 180 | 181 | in_uint8(s, result); 182 | if (result != 0) 183 | { 184 | error("AUrq: %d\n", result); 185 | return False; 186 | } 187 | 188 | if (opcode & 2) 189 | in_uint16_be(s, *mcs_userid); 190 | 191 | return s_check_end(s); 192 | } 193 | 194 | /* Send a CJrq message (ASN.1 PER) */ 195 | static void 196 | mcs_send_cjrq(uint16 chanid) 197 | { 198 | STREAM s; 199 | 200 | DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid)); 201 | 202 | s = iso_init(5); 203 | 204 | out_uint8(s, (MCS_CJRQ << 2)); 205 | out_uint16_be(s, g_mcs_userid); 206 | out_uint16_be(s, chanid); 207 | 208 | s_mark_end(s); 209 | iso_send(s); 210 | } 211 | 212 | /* Expect a CJcf message (ASN.1 PER) */ 213 | static RD_BOOL 214 | mcs_recv_cjcf(void) 215 | { 216 | uint8 opcode, result; 217 | STREAM s; 218 | 219 | s = iso_recv(NULL); 220 | if (s == NULL) 221 | return False; 222 | 223 | in_uint8(s, opcode); 224 | if ((opcode >> 2) != MCS_CJCF) 225 | { 226 | error("expected CJcf, got %d\n", opcode); 227 | return False; 228 | } 229 | 230 | in_uint8(s, result); 231 | if (result != 0) 232 | { 233 | error("CJrq: %d\n", result); 234 | return False; 235 | } 236 | 237 | in_uint8s(s, 4); /* mcs_userid, req_chanid */ 238 | if (opcode & 2) 239 | in_uint8s(s, 2); /* join_chanid */ 240 | 241 | return s_check_end(s); 242 | } 243 | 244 | /* Initialise an MCS transport data packet */ 245 | STREAM 246 | mcs_init(int length) 247 | { 248 | STREAM s; 249 | 250 | s = iso_init(length + 8); 251 | s_push_layer(s, mcs_hdr, 8); 252 | 253 | return s; 254 | } 255 | 256 | /* Send an MCS transport data packet to a specific channel */ 257 | void 258 | mcs_send_to_channel(STREAM s, uint16 channel) 259 | { 260 | uint16 length; 261 | 262 | s_pop_layer(s, mcs_hdr); 263 | length = (uint16)(s->end - s->p - 8); 264 | length |= 0x8000; 265 | 266 | out_uint8(s, (MCS_SDRQ << 2)); 267 | out_uint16_be(s, g_mcs_userid); 268 | out_uint16_be(s, channel); 269 | out_uint8(s, 0x70); /* flags */ 270 | out_uint16_be(s, length); 271 | 272 | iso_send(s); 273 | } 274 | 275 | /* Send an MCS transport data packet to the global channel */ 276 | void 277 | mcs_send(STREAM s) 278 | { 279 | mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL); 280 | } 281 | 282 | /* Receive an MCS transport data packet */ 283 | STREAM 284 | mcs_recv(uint16 * channel, uint8 * rdpver) 285 | { 286 | uint8 opcode, appid, length; 287 | STREAM s; 288 | 289 | s = iso_recv(rdpver); 290 | if (s == NULL) 291 | return NULL; 292 | if (rdpver != NULL) 293 | if (*rdpver != 3) 294 | return s; 295 | in_uint8(s, opcode); 296 | appid = opcode >> 2; 297 | if (appid != MCS_SDIN) 298 | { 299 | if (appid != MCS_DPUM) 300 | { 301 | STATUS(0, "expected data, got %d\n", opcode); 302 | } 303 | 304 | if (appid == MCS_DPUM) 305 | { 306 | extern char g_targetaddr[]; 307 | RESULT("VULNERABLE - got appid\n", g_targetaddr); 308 | } 309 | 310 | return NULL; 311 | } 312 | in_uint8s(s, 2); /* userid */ 313 | in_uint16_be(s, *channel); 314 | in_uint8s(s, 1); /* flags */ 315 | in_uint8(s, length); 316 | if (length & 0x80) 317 | in_uint8s(s, 1); /* second byte of length */ 318 | return s; 319 | } 320 | 321 | RD_BOOL 322 | mcs_connect_start(char *server, char *username, char *domain, char *password, 323 | RD_BOOL reconnect, uint32 * selected_protocol) 324 | { 325 | return iso_connect(server, username, domain, password, reconnect, selected_protocol); 326 | } 327 | 328 | RD_BOOL 329 | mcs_connect_finalize(STREAM mcs_data) 330 | { 331 | unsigned int i; 332 | 333 | mcs_send_connect_initial(mcs_data); 334 | if (!mcs_recv_connect_response(mcs_data)) 335 | goto error; 336 | 337 | mcs_send_edrq(); 338 | 339 | mcs_send_aurq(); 340 | if (!mcs_recv_aucf(&g_mcs_userid)) 341 | goto error; 342 | 343 | mcs_send_cjrq(g_mcs_userid + MCS_USERCHANNEL_BASE); 344 | 345 | if (!mcs_recv_cjcf()) 346 | goto error; 347 | 348 | mcs_send_cjrq(MCS_GLOBAL_CHANNEL); 349 | if (!mcs_recv_cjcf()) 350 | goto error; 351 | 352 | STATUS(3, "[+] sending %u channels\n", (unsigned)g_num_channels); 353 | 354 | for (i = 0; i < g_num_channels; i++) 355 | { 356 | mcs_send_cjrq(g_channels[i].mcs_id); 357 | if (!mcs_recv_cjcf()) 358 | goto error; 359 | } 360 | return True; 361 | 362 | error: 363 | iso_disconnect(); 364 | return False; 365 | } 366 | 367 | /* Disconnect from the MCS layer */ 368 | void 369 | mcs_disconnect(void) 370 | { 371 | iso_disconnect(); 372 | } 373 | 374 | /* reset the state of the mcs layer */ 375 | void 376 | mcs_reset_state(void) 377 | { 378 | g_mcs_userid = 0; 379 | iso_reset_state(); 380 | } 381 | -------------------------------------------------------------------------------- /src/rand-blackrock.c: -------------------------------------------------------------------------------- 1 | /* 2 | BlackRock cipher 3 | 4 | (h/t Marsh Ray @marshray for this idea) 5 | 6 | This is a randomization/reshuffling function based on a crypto 7 | "Feistel network" as describ ed in the paper: 8 | 9 | 'Ciphers with Arbitrary Finite Domains' 10 | by John Black and Phillip Rogaway 11 | http://www.cs.ucdavis.edu/~rogaway/papers/subset.pdf 12 | 13 | This is a crypto-like construction that encrypts an arbitrary sized 14 | range. Given a number in the range [0..9999], it'll produce a mapping 15 | to a distinct different number in the same range (and back again). 16 | In other words, it randomizes the order of numbers in a sequence. 17 | 18 | For example, it can be used to randomize the sequence [0..9]: 19 | 20 | 0 -> 6 21 | 1 -> 4 22 | 2 -> 8 23 | 3 -> 1 24 | 4 -> 9 25 | 5 -> 3 26 | 6 -> 0 27 | 7 -> 5 28 | 8 -> 2 29 | 9 -> 7 30 | 31 | As you can see on the right hand side, the numbers are in random 32 | order, and they don't repeaet. 33 | 34 | This is create for port scanning. We can take an index variable 35 | and increment it during a scan, then use this function to 36 | randomize it, yet be assured that we've probed every IP and port 37 | within the range. 38 | 39 | The cryptographic strength of this construction depends upon the 40 | number of rounds, and the exact nature of the inner "READ()" function. 41 | Because it's a Feistel network, that "READ()" function can be almost 42 | anything. 43 | 44 | We don't care about cryptographic strength, just speed, so we are 45 | using a trivial READ() function. 46 | 47 | This is a class of "format-preserving encryption". There are 48 | probably better constructions than what I'm using. 49 | */ 50 | #include "rand-blackrock.h" 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | 59 | #if defined(_MSC_VER) 60 | #define inline _inline 61 | #endif 62 | 63 | /*************************************************************************** 64 | * It's an s-box. You gotta have an s-box 65 | ***************************************************************************/ 66 | const unsigned char sbox[256] = { 67 | 0x91, 0x58, 0xb3, 0x31, 0x6c, 0x33, 0xda, 0x88, 68 | 0x57, 0xdd, 0x8c, 0xf2, 0x29, 0x5a, 0x08, 0x9f, 69 | 0x49, 0x34, 0xce, 0x99, 0x9e, 0xbf, 0x0f, 0x81, 70 | 0xd4, 0x2f, 0x92, 0x3f, 0x95, 0xf5, 0x23, 0x00, 71 | 0x0d, 0x3e, 0xa8, 0x90, 0x98, 0xdd, 0x20, 0x00, 72 | 0x03, 0x69, 0x0a, 0xca, 0xba, 0x12, 0x08, 0x41, 73 | 0x6e, 0xb9, 0x86, 0xe4, 0x50, 0xf0, 0x84, 0xe2, 74 | 0xb3, 0xb3, 0xc8, 0xb5, 0xb2, 0x2d, 0x18, 0x70, 75 | 76 | 0x0a, 0xd7, 0x92, 0x90, 0x9e, 0x1e, 0x0c, 0x1f, 77 | 0x08, 0xe8, 0x06, 0xfd, 0x85, 0x2f, 0xaa, 0x5d, 78 | 0xcf, 0xf9, 0xe3, 0x55, 0xb9, 0xfe, 0xa6, 0x7f, 79 | 0x44, 0x3b, 0x4a, 0x4f, 0xc9, 0x2f, 0xd2, 0xd3, 80 | 0x8e, 0xdc, 0xae, 0xba, 0x4f, 0x02, 0xb4, 0x76, 81 | 0xba, 0x64, 0x2d, 0x07, 0x9e, 0x08, 0xec, 0xbd, 82 | 0x52, 0x29, 0x07, 0xbb, 0x9f, 0xb5, 0x58, 0x6f, 83 | 0x07, 0x55, 0xb0, 0x34, 0x74, 0x9f, 0x05, 0xb2, 84 | 85 | 0xdf, 0xa9, 0xc6, 0x2a, 0xa3, 0x5d, 0xff, 0x10, 86 | 0x40, 0xb3, 0xb7, 0xb4, 0x63, 0x6e, 0xf4, 0x3e, 87 | 0xee, 0xf6, 0x49, 0x52, 0xe3, 0x11, 0xb3, 0xf1, 88 | 0xfb, 0x60, 0x48, 0xa1, 0xa4, 0x19, 0x7a, 0x2e, 89 | 0x90, 0x28, 0x90, 0x8d, 0x5e, 0x8c, 0x8c, 0xc4, 90 | 0xf2, 0x4a, 0xf6, 0xb2, 0x19, 0x83, 0xea, 0xed, 91 | 0x6d, 0xba, 0xfe, 0xd8, 0xb6, 0xa3, 0x5a, 0xb4, 92 | 0x48, 0xfa, 0xbe, 0x5c, 0x69, 0xac, 0x3c, 0x8f, 93 | 94 | 0x63, 0xaf, 0xa4, 0x42, 0x25, 0x50, 0xab, 0x65, 95 | 0x80, 0x65, 0xb9, 0xfb, 0xc7, 0xf2, 0x2d, 0x5c, 96 | 0xe3, 0x4c, 0xa4, 0xa6, 0x8e, 0x07, 0x9c, 0xeb, 97 | 0x41, 0x93, 0x65, 0x44, 0x4a, 0x86, 0xc1, 0xf6, 98 | 0x2c, 0x97, 0xfd, 0xf4, 0x6c, 0xdc, 0xe1, 0xe0, 99 | 0x28, 0xd9, 0x89, 0x7b, 0x09, 0xe2, 0xa0, 0x38, 100 | 0x74, 0x4a, 0xa6, 0x5e, 0xd2, 0xe2, 0x4d, 0xf3, 101 | 0xf4, 0xc6, 0xbc, 0xa2, 0x51, 0x58, 0xe8, 0xae, 102 | }; 103 | 104 | /*************************************************************************** 105 | ***************************************************************************/ 106 | static double my_sqrt(double n){ 107 | double lo = 0, hi = n, mid = n; 108 | int i; 109 | for(i = 0 ; i < 1000 ; i++){ 110 | mid = (lo+hi)/2; 111 | if(mid*mid == n) return mid; 112 | if(mid*mid > n) hi = mid; 113 | else lo = mid; 114 | } 115 | return mid; 116 | } 117 | 118 | /*************************************************************************** 119 | ***************************************************************************/ 120 | void 121 | blackrock_init(struct BlackRock *br, uint64_t range, uint64_t seed, unsigned rounds) 122 | { 123 | double foo = my_sqrt(range * 1.0); 124 | 125 | /* This algorithm gets very non-random at small numbers, so I'm going 126 | * to try to fix some constants here to make it work. It doesn't have 127 | * to be good, since it's kinda pointless having ranges this small */ 128 | switch (range) { 129 | case 0: 130 | br->a = 0; 131 | br->b = 0; 132 | break; 133 | case 1: 134 | br->a = 1; 135 | br->b = 1; 136 | break; 137 | case 2: 138 | br->a = 1; 139 | br->b = 2; 140 | break; 141 | case 3: 142 | br->a = 2; 143 | br->b = 2; 144 | break; 145 | case 4: 146 | case 5: 147 | case 6: 148 | br->a = 2; 149 | br->b = 3; 150 | break; 151 | case 7: 152 | case 8: 153 | br->a = 3; 154 | br->b = 3; 155 | break; 156 | default: 157 | br->range = range; 158 | br->a = (uint64_t)(foo - 2); 159 | br->b = (uint64_t)(foo + 3); 160 | break; 161 | } 162 | 163 | while (br->a * br->b <= range) 164 | br->b++; 165 | 166 | br->rounds = rounds; 167 | br->seed = seed; 168 | br->range = range; 169 | } 170 | 171 | 172 | /*************************************************************************** 173 | * The inner round/mixer function. In DES, it's a series of S-box lookups, 174 | * which 175 | ***************************************************************************/ 176 | static inline uint64_t 177 | READ(uint64_t r, uint64_t R, uint64_t seed) 178 | { 179 | uint64_t r0, r1, r2, r3; 180 | 181 | #define GETBYTE(R,n) ((((R)>>(n*8))^seed^r)&0xFF) 182 | 183 | R ^= (seed << r) ^ (seed >> (64 - r)); 184 | 185 | r0 = sbox[GETBYTE(R,0)]<< 0 | sbox[GETBYTE(R,1)]<< 8; 186 | r1 = (sbox[GETBYTE(R,2)]<<16UL | sbox[GETBYTE(R,3)]<<24UL)&0x0ffffFFFFUL; 187 | r2 = sbox[GETBYTE(R,4)]<< 0 | sbox[GETBYTE(R,5)]<< 8; 188 | r3 = (sbox[GETBYTE(R,6)]<<16UL | sbox[GETBYTE(R,7)]<<24UL)&0x0ffffFFFFUL; 189 | 190 | R = r0 ^ r1 ^ r2<<23UL ^ r3<<33UL; 191 | 192 | return R; 193 | } 194 | 195 | 196 | /*************************************************************************** 197 | * 198 | * NOTE: 199 | * the names in this function are cryptic in order to match as closely 200 | * as possible the pseudocode in the following paper: 201 | * http://www.cs.ucdavis.edu/~rogaway/papers/subset.pdf 202 | * Read that paper in order to understand this code. 203 | ***************************************************************************/ 204 | static inline uint64_t 205 | ENCRYPT(unsigned r, uint64_t a, uint64_t b, uint64_t m, uint64_t seed) 206 | { 207 | uint64_t L, R; 208 | unsigned j; 209 | uint64_t tmp; 210 | 211 | L = m % a; 212 | R = m / a; 213 | 214 | for (j=1; j<=r; j++) { 215 | if (j & 1) { 216 | tmp = (L + READ(j, R, seed)) % a; 217 | } else { 218 | tmp = (L + READ(j, R, seed)) % b; 219 | } 220 | L = R; 221 | R = tmp; 222 | } 223 | if (r & 1) { 224 | return a * L + R; 225 | } else { 226 | return a * R + L; 227 | } 228 | } 229 | 230 | /*************************************************************************** 231 | ***************************************************************************/ 232 | static inline uint64_t 233 | UNENCRYPT(unsigned r, uint64_t a, uint64_t b, uint64_t m, uint64_t seed) 234 | { 235 | uint64_t L, R; 236 | unsigned j; 237 | uint64_t tmp; 238 | 239 | if (r & 1) { 240 | R = m % a; 241 | L = m / a; 242 | } else { 243 | L = m % a; 244 | R = m / a; 245 | } 246 | 247 | for (j=r; j>=1; j--) { 248 | if (j & 1) { 249 | tmp = READ(j, L, seed); 250 | if (tmp > R) { 251 | tmp = (tmp - R); 252 | tmp = a - (tmp%a); 253 | if (tmp == a) 254 | tmp = 0; 255 | } else { 256 | tmp = (R - tmp); 257 | tmp %= a; 258 | } 259 | } else { 260 | tmp = READ(j, L, seed); 261 | if (tmp > R) { 262 | tmp = (tmp - R); 263 | tmp = b - (tmp%b); 264 | if (tmp == b) 265 | tmp = 0; 266 | } else { 267 | tmp = (R - tmp); 268 | tmp %= b; 269 | } 270 | } 271 | R = L; 272 | L = tmp; 273 | } 274 | return a * R + L; 275 | } 276 | 277 | /*************************************************************************** 278 | ***************************************************************************/ 279 | uint64_t 280 | blackrock_shuffle(const struct BlackRock *br, uint64_t m) 281 | { 282 | uint64_t c; 283 | 284 | c = ENCRYPT(br->rounds, br->a, br->b, m, br->seed); 285 | while (c >= br->range) 286 | c = ENCRYPT(br->rounds, br->a, br->b, c, br->seed); 287 | 288 | return c; 289 | } 290 | 291 | /*************************************************************************** 292 | ***************************************************************************/ 293 | uint64_t 294 | blackrock_unshuffle(const struct BlackRock *br, uint64_t m) 295 | { 296 | uint64_t c; 297 | 298 | c = UNENCRYPT(br->rounds, br->a, br->b, m, br->seed); 299 | while (c >= br->range) 300 | c = UNENCRYPT(br->rounds, br->a, br->b, c, br->seed); 301 | 302 | return c; 303 | } 304 | 305 | 306 | -------------------------------------------------------------------------------- /src/mppc.c: -------------------------------------------------------------------------------- 1 | /* -*- c-basic-offset: 8 -*- 2 | rdesktop: A Remote Desktop Protocol client. 3 | Protocol services - RDP decompression 4 | Copyright (C) Matthew Chapman 1999-2008 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #include "rdesktop.h" 24 | 25 | /* mppc decompression */ 26 | /* http://www.faqs.org/rfcs/rfc2118.html */ 27 | 28 | /* Contacts: */ 29 | 30 | /* hifn contact mentioned in the faq is */ 31 | /* Robert Friend rfriend at hifn dot com */ 32 | 33 | /* if you have questions regarding MPPC */ 34 | /* our contact is */ 35 | /* Guus Dhaeze GDhaeze at hifn dot com */ 36 | 37 | /* Licensing: */ 38 | 39 | /* decompression is alright as long as we */ 40 | /* don't compress data */ 41 | 42 | /* Algorithm: */ 43 | 44 | /* as the rfc states the algorithm seems to */ 45 | /* be LZ77 with a sliding buffer */ 46 | /* that is empty at init. */ 47 | 48 | /* the algorithm is called LZS and is */ 49 | /* patented for another couple of years. */ 50 | 51 | /* more information is available in */ 52 | /* http://www.ietf.org/ietf/IPR/hifn-ipr-draft-friend-tls-lzs-compression.txt */ 53 | 54 | 55 | RDPCOMP g_mppc_dict; 56 | 57 | int 58 | mppc_expand(uint8 * data, uint32 clen, uint8 ctype, uint32 * roff, uint32 * rlen) 59 | { 60 | int k, walker_len = 0, walker; 61 | uint32 i = 0; 62 | int next_offset, match_off; 63 | int match_len; 64 | int old_offset, match_bits; 65 | RD_BOOL big = ctype & RDP_MPPC_BIG ? True : False; 66 | 67 | uint8 *dict = g_mppc_dict.hist; 68 | 69 | if ((ctype & RDP_MPPC_COMPRESSED) == 0) 70 | { 71 | *roff = 0; 72 | *rlen = clen; 73 | return 0; 74 | } 75 | 76 | if ((ctype & RDP_MPPC_RESET) != 0) 77 | { 78 | g_mppc_dict.roff = 0; 79 | } 80 | 81 | if ((ctype & RDP_MPPC_FLUSH) != 0) 82 | { 83 | memset(dict, 0, RDP_MPPC_DICT_SIZE); 84 | g_mppc_dict.roff = 0; 85 | } 86 | 87 | *roff = 0; 88 | *rlen = 0; 89 | 90 | walker = g_mppc_dict.roff; 91 | 92 | next_offset = walker; 93 | old_offset = next_offset; 94 | *roff = old_offset; 95 | if (clen == 0) 96 | return 0; 97 | clen += i; 98 | 99 | do 100 | { 101 | if (walker_len == 0) 102 | { 103 | if (i >= clen) 104 | break; 105 | walker = data[i++] << 24; 106 | walker_len = 8; 107 | } 108 | if (walker >= 0) 109 | { 110 | if (walker_len < 8) 111 | { 112 | if (i >= clen) 113 | { 114 | if (walker != 0) 115 | return -1; 116 | break; 117 | } 118 | walker |= (data[i++] & 0xff) << (24 - walker_len); 119 | walker_len += 8; 120 | } 121 | if (next_offset >= RDP_MPPC_DICT_SIZE) 122 | return -1; 123 | dict[next_offset++] = (((uint32) walker) >> ((uint32) 24)); 124 | walker <<= 8; 125 | walker_len -= 8; 126 | continue; 127 | } 128 | walker <<= 1; 129 | /* fetch next 8-bits */ 130 | if (--walker_len == 0) 131 | { 132 | if (i >= clen) 133 | return -1; 134 | walker = data[i++] << 24; 135 | walker_len = 8; 136 | } 137 | /* literal decoding */ 138 | if (walker >= 0) 139 | { 140 | if (walker_len < 8) 141 | { 142 | if (i >= clen) 143 | return -1; 144 | walker |= (data[i++] & 0xff) << (24 - walker_len); 145 | walker_len += 8; 146 | } 147 | if (next_offset >= RDP_MPPC_DICT_SIZE) 148 | return -1; 149 | dict[next_offset++] = (uint8) (walker >> 24 | 0x80); 150 | walker <<= 8; 151 | walker_len -= 8; 152 | continue; 153 | } 154 | 155 | /* decode offset */ 156 | /* length pair */ 157 | walker <<= 1; 158 | if (--walker_len < (big ? 3 : 2)) 159 | { 160 | if (i >= clen) 161 | return -1; 162 | walker |= (data[i++] & 0xff) << (24 - walker_len); 163 | walker_len += 8; 164 | } 165 | 166 | if (big) 167 | { 168 | /* offset decoding where offset len is: 169 | -63: 11111 followed by the lower 6 bits of the value 170 | 64-319: 11110 followed by the lower 8 bits of the value ( value - 64 ) 171 | 320-2367: 1110 followed by lower 11 bits of the value ( value - 320 ) 172 | 2368-65535: 110 followed by lower 16 bits of the value ( value - 2368 ) 173 | */ 174 | switch (((uint32) walker) >> ((uint32) 29)) 175 | { 176 | case 7: /* - 63 */ 177 | for (; walker_len < 9; walker_len += 8) 178 | { 179 | if (i >= clen) 180 | return -1; 181 | walker |= (data[i++] & 0xff) << (24 - walker_len); 182 | } 183 | walker <<= 3; 184 | match_off = ((uint32) walker) >> ((uint32) 26); 185 | walker <<= 6; 186 | walker_len -= 9; 187 | break; 188 | 189 | case 6: /* 64 - 319 */ 190 | for (; walker_len < 11; walker_len += 8) 191 | { 192 | if (i >= clen) 193 | return -1; 194 | walker |= (data[i++] & 0xff) << (24 - walker_len); 195 | } 196 | 197 | walker <<= 3; 198 | match_off = (((uint32) walker) >> ((uint32) 24)) + 64; 199 | walker <<= 8; 200 | walker_len -= 11; 201 | break; 202 | 203 | case 5: 204 | case 4: /* 320 - 2367 */ 205 | for (; walker_len < 13; walker_len += 8) 206 | { 207 | if (i >= clen) 208 | return -1; 209 | walker |= (data[i++] & 0xff) << (24 - walker_len); 210 | } 211 | 212 | walker <<= 2; 213 | match_off = (((uint32) walker) >> ((uint32) 21)) + 320; 214 | walker <<= 11; 215 | walker_len -= 13; 216 | break; 217 | 218 | default: /* 2368 - 65535 */ 219 | for (; walker_len < 17; walker_len += 8) 220 | { 221 | if (i >= clen) 222 | return -1; 223 | walker |= (data[i++] & 0xff) << (24 - walker_len); 224 | } 225 | 226 | walker <<= 1; 227 | match_off = (((uint32) walker) >> ((uint32) 16)) + 2368; 228 | walker <<= 16; 229 | walker_len -= 17; 230 | break; 231 | } 232 | } 233 | else 234 | { 235 | /* offset decoding where offset len is: 236 | -63: 1111 followed by the lower 6 bits of the value 237 | 64-319: 1110 followed by the lower 8 bits of the value ( value - 64 ) 238 | 320-8191: 110 followed by the lower 13 bits of the value ( value - 320 ) 239 | */ 240 | switch (((uint32) walker) >> ((uint32) 30)) 241 | { 242 | case 3: /* - 63 */ 243 | if (walker_len < 8) 244 | { 245 | if (i >= clen) 246 | return -1; 247 | walker |= (data[i++] & 0xff) << (24 - walker_len); 248 | walker_len += 8; 249 | } 250 | walker <<= 2; 251 | match_off = ((uint32) walker) >> ((uint32) 26); 252 | walker <<= 6; 253 | walker_len -= 8; 254 | break; 255 | 256 | case 2: /* 64 - 319 */ 257 | for (; walker_len < 10; walker_len += 8) 258 | { 259 | if (i >= clen) 260 | return -1; 261 | walker |= (data[i++] & 0xff) << (24 - walker_len); 262 | } 263 | 264 | walker <<= 2; 265 | match_off = (((uint32) walker) >> ((uint32) 24)) + 64; 266 | walker <<= 8; 267 | walker_len -= 10; 268 | break; 269 | 270 | default: /* 320 - 8191 */ 271 | for (; walker_len < 14; walker_len += 8) 272 | { 273 | if (i >= clen) 274 | return -1; 275 | walker |= (data[i++] & 0xff) << (24 - walker_len); 276 | } 277 | 278 | match_off = (walker >> 18) + 320; 279 | walker <<= 14; 280 | walker_len -= 14; 281 | break; 282 | } 283 | } 284 | if (walker_len == 0) 285 | { 286 | if (i >= clen) 287 | return -1; 288 | walker = data[i++] << 24; 289 | walker_len = 8; 290 | } 291 | 292 | /* decode length of match */ 293 | match_len = 0; 294 | if (walker >= 0) 295 | { /* special case - length of 3 is in bit 0 */ 296 | match_len = 3; 297 | walker <<= 1; 298 | walker_len--; 299 | } 300 | else 301 | { 302 | /* this is how it works len of: 303 | 4-7: 10 followed by 2 bits of the value 304 | 8-15: 110 followed by 3 bits of the value 305 | 16-31: 1110 followed by 4 bits of the value 306 | 32-63: .... and so forth 307 | 64-127: 308 | 128-255: 309 | 256-511: 310 | 512-1023: 311 | 1024-2047: 312 | 2048-4095: 313 | 4096-8191: 314 | 315 | i.e. 4097 is encoded as: 111111111110 000000000001 316 | meaning 4096 + 1... 317 | */ 318 | match_bits = big ? 14 : 11; /* 11 or 14 bits of value at most */ 319 | do 320 | { 321 | walker <<= 1; 322 | if (--walker_len == 0) 323 | { 324 | if (i >= clen) 325 | return -1; 326 | walker = data[i++] << 24; 327 | walker_len = 8; 328 | } 329 | if (walker >= 0) 330 | break; 331 | if (--match_bits == 0) 332 | { 333 | return -1; 334 | } 335 | } 336 | while (1); 337 | match_len = (big ? 16 : 13) - match_bits; 338 | walker <<= 1; 339 | if (--walker_len < match_len) 340 | { 341 | for (; walker_len < match_len; walker_len += 8) 342 | { 343 | if (i >= clen) 344 | { 345 | return -1; 346 | } 347 | walker |= (data[i++] & 0xff) << (24 - walker_len); 348 | } 349 | } 350 | 351 | match_bits = match_len; 352 | match_len = 353 | ((walker >> (32 - match_bits)) & (~(-1 << match_bits))) | (1 << 354 | match_bits); 355 | walker <<= match_bits; 356 | walker_len -= match_bits; 357 | } 358 | if (next_offset + match_len >= RDP_MPPC_DICT_SIZE) 359 | { 360 | return -1; 361 | } 362 | /* memory areas can overlap - meaning we can't use memXXX functions */ 363 | k = (next_offset - match_off) & (big ? 65535 : 8191); 364 | do 365 | { 366 | dict[next_offset++] = dict[k++]; 367 | } 368 | while (--match_len != 0); 369 | } 370 | while (1); 371 | 372 | /* store history offset */ 373 | g_mppc_dict.roff = next_offset; 374 | 375 | *roff = old_offset; 376 | *rlen = next_offset - old_offset; 377 | 378 | return 0; 379 | } 380 | -------------------------------------------------------------------------------- /vs19/rdpscan.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {475F1C8A-F70D-45C0-95E5-EB783935277D} 24 | Win32Proj 25 | rdpscan 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | c:\Program Files (x86)\OpenSSL-Win32\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 76 | c:\Program Files (x86)\OpenSSL-Win32\lib;;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86 77 | 78 | 79 | true 80 | C:\Program Files\OpenSSL-Win64\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 81 | C:\Program Files\OpenSSL-Win64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 82 | 83 | 84 | false 85 | 86 | 87 | false 88 | 89 | 90 | 91 | 92 | 93 | Level3 94 | Disabled 95 | true 96 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 97 | true 98 | 99 | 100 | Console 101 | true 102 | 103 | 104 | 105 | 106 | 107 | 108 | Level3 109 | Disabled 110 | true 111 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 112 | true 113 | 114 | 115 | Console 116 | true 117 | 118 | 119 | 120 | 121 | 122 | 123 | Level3 124 | MaxSpeed 125 | true 126 | true 127 | true 128 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 129 | true 130 | 131 | 132 | Console 133 | true 134 | true 135 | true 136 | 137 | 138 | 139 | 140 | 141 | 142 | Level3 143 | MaxSpeed 144 | true 145 | true 146 | true 147 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 148 | true 149 | 150 | 151 | Console 152 | true 153 | true 154 | true 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /vs10/rdpscan.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {D116CC32-BC4F-4FAD-B09C-0D6459D1C1B6} 23 | Win32Proj 24 | rdpscan 25 | 26 | 27 | 28 | Application 29 | true 30 | Unicode 31 | 32 | 33 | Application 34 | true 35 | NotSet 36 | 37 | 38 | Application 39 | false 40 | true 41 | Unicode 42 | 43 | 44 | Application 45 | false 46 | true 47 | Unicode 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | true 67 | ../../openssl/include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; 68 | ../../openssl;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib 69 | 70 | 71 | true 72 | C:\Program Files\OpenSSL-Win64\include\;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; 73 | C:\Program Files\OpenSSL-Win64\lib\;$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSdkDir)lib\x64; 74 | 75 | 76 | false 77 | c:\dev\openssl\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; 78 | c:\dev\openssl\;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib 79 | 80 | 81 | false 82 | C:\Program Files\OpenSSL-Win64\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; 83 | $(VCInstallDir)atlmfc\lib\amd64;$(VCInstallDir)lib\amd64 84 | C:\Program Files\OpenSSL-Win64\lib;$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSdkDir)lib\x64; 85 | false 86 | 87 | 88 | 89 | 90 | 91 | Level3 92 | Disabled 93 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 94 | 95 | 96 | Console 97 | true 98 | msvcrtd.lib;%(IgnoreSpecificDefaultLibraries) 99 | 100 | 101 | 102 | 103 | 104 | 105 | Level3 106 | Disabled 107 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | true 109 | 110 | 111 | Console 112 | true 113 | 114 | 115 | 116 | 117 | Level3 118 | 119 | 120 | MaxSpeed 121 | true 122 | true 123 | SSLSTATIC;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 124 | MultiThreaded 125 | 126 | 127 | Console 128 | true 129 | true 130 | true 131 | 132 | 133 | 134 | 135 | Level3 136 | 137 | 138 | MaxSpeed 139 | true 140 | true 141 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 142 | MultiThreaded 143 | 144 | 145 | Console 146 | true 147 | true 148 | true 149 | false 150 | libcmt.lib 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /src/iso.c: -------------------------------------------------------------------------------- 1 | /* -*- c-basic-offset: 8 -*- 2 | rdesktop: A Remote Desktop Protocol client. 3 | Protocol services - ISO layer 4 | Copyright (C) Matthew Chapman 1999-2008 5 | Copyright 2005-2011 Peter Astrand for Cendio AB 6 | Copyright 2012 Henrik Andersson for Cendio AB 7 | 8 | This program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | #include "rdesktop.h" 23 | #include "util-log.h" 24 | #include "tcp.h" 25 | 26 | #include 27 | 28 | extern RD_BOOL g_encryption; 29 | extern RD_BOOL g_encryption_initial; 30 | extern RDP_VERSION g_rdp_version; 31 | extern RD_BOOL g_use_password_as_pin; 32 | 33 | static RD_BOOL g_negotiate_rdp_protocol = True; 34 | 35 | extern char *g_sc_csp_name; 36 | extern char *g_sc_reader_name; 37 | extern char *g_sc_card_name; 38 | extern char *g_sc_container_name; 39 | 40 | 41 | /* Send a self-contained ISO PDU */ 42 | static void 43 | iso_send_msg(uint8 code) 44 | { 45 | STREAM s; 46 | 47 | s = tcp_init(11); 48 | 49 | out_uint8(s, 3); /* version */ 50 | out_uint8(s, 0); /* reserved */ 51 | out_uint16_be(s, 11); /* length */ 52 | 53 | out_uint8(s, 6); /* hdrlen */ 54 | out_uint8(s, code); 55 | out_uint16(s, 0); /* dst_ref */ 56 | out_uint16(s, 0); /* src_ref */ 57 | out_uint8(s, 0); /* class */ 58 | 59 | s_mark_end(s); 60 | tcp_send(s); 61 | } 62 | 63 | static void 64 | iso_send_connection_request(char *username, uint32 neg_proto) 65 | { 66 | STREAM s; 67 | int length = 30 + (int)strlen(username); 68 | 69 | if (g_rdp_version >= RDP_V5 && g_negotiate_rdp_protocol) 70 | length += 8; 71 | 72 | s = tcp_init(length); 73 | 74 | out_uint8(s, 3); /* version */ 75 | out_uint8(s, 0); /* reserved */ 76 | out_uint16_be(s, length); /* length */ 77 | 78 | out_uint8(s, length - 5); /* hdrlen */ 79 | out_uint8(s, ISO_PDU_CR); 80 | out_uint16(s, 0); /* dst_ref */ 81 | out_uint16(s, 0); /* src_ref */ 82 | out_uint8(s, 0); /* class */ 83 | 84 | out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash=")); 85 | out_uint8p(s, username, strlen(username)); 86 | 87 | out_uint8(s, 0x0d); /* cookie termination string: CR+LF */ 88 | out_uint8(s, 0x0a); 89 | 90 | if (g_rdp_version >= RDP_V5 && g_negotiate_rdp_protocol) 91 | { 92 | /* optional rdp protocol negotiation request for RDPv5 */ 93 | out_uint8(s, RDP_NEG_REQ); 94 | out_uint8(s, 0); 95 | out_uint16(s, 8); 96 | out_uint32(s, neg_proto); 97 | } 98 | 99 | s_mark_end(s); 100 | tcp_send(s); 101 | 102 | 103 | } 104 | 105 | /* Receive a message on the ISO layer, return code */ 106 | static STREAM 107 | iso_recv_msg(uint8 * code, uint8 * rdpver) 108 | { 109 | STREAM s; 110 | uint16 length; 111 | uint8 version; 112 | extern int g_is_iso_confirmed; 113 | 114 | s = tcp_recv(NULL, 4); 115 | if (s == NULL) 116 | return NULL; 117 | in_uint8(s, version); 118 | if (rdpver != NULL) 119 | *rdpver = version; 120 | if (version == 3) 121 | { 122 | in_uint8s(s, 1); /* pad */ 123 | in_uint16_be(s, length); 124 | } 125 | else if (s->end - s->data == 4 && memcmp(s->data, "SSH-", 4) == 0) 126 | { 127 | RESULT("SAFE - not RDP - SSH response seen\n"); 128 | return NULL; 129 | } 130 | else if (s->end - s->data == 4 && memcmp(s->data, "HTTP", 4) == 0) 131 | { 132 | RESULT("SAFE - not RDP - SSH response seen\n"); 133 | return NULL; 134 | } 135 | else if (!g_is_iso_confirmed) 136 | { 137 | /* This is the first response, make sure it's v3 */ 138 | RESULT("SAFE - not RDP - unknown response received\n"); 139 | return NULL; 140 | } 141 | else 142 | { 143 | in_uint8(s, length); 144 | if (length & 0x80) 145 | { 146 | length &= ~0x80; 147 | next_be(s, length); 148 | } 149 | } 150 | if (length < 4) 151 | { 152 | error("Bad packet header\n"); 153 | return NULL; 154 | } 155 | s = tcp_recv(s, length - 4); 156 | if (s == NULL) 157 | return NULL; 158 | if (version != 3) 159 | return s; 160 | in_uint8s(s, 1); /* hdrlen */ 161 | in_uint8(s, *code); 162 | if (*code == ISO_PDU_DT) 163 | { 164 | in_uint8s(s, 1); /* eot */ 165 | return s; 166 | } 167 | in_uint8s(s, 5); /* dst_ref, src_ref, class */ 168 | return s; 169 | } 170 | 171 | /* Initialise ISO transport data packet */ 172 | STREAM 173 | iso_init(int length) 174 | { 175 | STREAM s; 176 | 177 | s = tcp_init(length + 7); 178 | s_push_layer(s, iso_hdr, 7); 179 | 180 | return s; 181 | } 182 | 183 | /* Send an ISO data PDU */ 184 | void 185 | iso_send(STREAM s) 186 | { 187 | uint16 length; 188 | 189 | s_pop_layer(s, iso_hdr); 190 | length = (uint16)(s->end - s->p); 191 | 192 | out_uint8(s, 3); /* version */ 193 | out_uint8(s, 0); /* reserved */ 194 | out_uint16_be(s, length); 195 | 196 | out_uint8(s, 2); /* hdrlen */ 197 | out_uint8(s, ISO_PDU_DT); /* code */ 198 | out_uint8(s, 0x80); /* eot */ 199 | 200 | tcp_send(s); 201 | } 202 | 203 | /* Receive ISO transport data packet */ 204 | STREAM 205 | iso_recv(uint8 * rdpver) 206 | { 207 | STREAM s; 208 | uint8 code = 0; 209 | 210 | s = iso_recv_msg(&code, rdpver); 211 | if (s == NULL) 212 | return NULL; 213 | if (rdpver != NULL) 214 | if (*rdpver != 3) 215 | return s; 216 | if (code != ISO_PDU_DT) 217 | { 218 | error("expected DT, got 0x%x\n", code); 219 | return NULL; 220 | } 221 | return s; 222 | } 223 | 224 | /* Establish a connection up to the ISO layer */ 225 | RD_BOOL 226 | iso_connect(char *server, char *username, char *domain, char *password, 227 | RD_BOOL reconnect, uint32 * selected_protocol) 228 | { 229 | STREAM s; 230 | uint8 code; 231 | uint32 neg_proto = 0; 232 | extern int g_connect_retries; 233 | extern int g_is_credssp_enabled; 234 | extern int g_is_ssl_enabled; 235 | 236 | g_negotiate_rdp_protocol = True; 237 | 238 | /* By default, this is true, SSL is enabled by default unless 239 | * '--nossl' is configured on the command-line */ 240 | if (g_is_ssl_enabled) 241 | neg_proto |= PROTOCOL_SSL; 242 | 243 | /* By default, this is false, CredSSP/NLA is disabled by default 244 | * unless '--credssp' is enabled on the command-line */ 245 | if (g_is_credssp_enabled) 246 | neg_proto |= PROTOCOL_HYBRID; 247 | 248 | #ifdef WITH_CREDSSP 249 | if (!g_use_password_as_pin) 250 | neg_proto |= PROTOCOL_HYBRID; 251 | else if (g_sc_csp_name || g_sc_reader_name || g_sc_card_name || g_sc_container_name) 252 | neg_proto |= PROTOCOL_HYBRID; 253 | else 254 | warning("Disables CredSSP due to missing smartcard information for SSO.\n"); 255 | #endif 256 | 257 | retry: 258 | *selected_protocol = PROTOCOL_RDP; 259 | code = 0; 260 | 261 | if (!tcp_connect(server)) { 262 | return False; 263 | } 264 | 265 | iso_send_connection_request(username, neg_proto); 266 | 267 | s = iso_recv_msg(&code, NULL); 268 | if (s == NULL) { 269 | /* Servers that allow connctions seem to sometimes RST/FIN then 270 | * at the beginning, so if that's the case, retry the connection 271 | * a couple of times */ 272 | if (g_connect_retries) 273 | goto retry; 274 | return False; 275 | } 276 | 277 | if (code != ISO_PDU_CC) 278 | { 279 | STATUS(1, "expected CC, got 0x%x\n", code); 280 | if (s->end - s->data > 7 && memcmp(s->data, "HTTP/1.", 7) == 0) { 281 | RESULT("SAFE - not RDP - HTTP response seen\n"); 282 | } else if (s->end - s->data > 7 && memcmp(s->data, "SSH-2.0", 7) == 0) { 283 | RESULT("SAFE - not RDP - SSH response seen\n"); 284 | } else 285 | RESULT("SAFE - not RDP - unknown response seen\n"); 286 | tcp_disconnect(); 287 | return False; 288 | } else { 289 | /* Mark this as a successfull ISO COTP connection, to 290 | * differentiate against other protocols */ 291 | extern int g_is_iso_confirmed; 292 | g_is_iso_confirmed = 1; 293 | } 294 | 295 | if (g_rdp_version >= RDP_V5 && s_check_rem(s, 8)) 296 | { 297 | /* handle RDP_NEG_REQ response */ 298 | const char *reason = NULL; 299 | 300 | uint8 type = 0, flags = 0; 301 | uint16 length = 0; 302 | uint32 data = 0; 303 | 304 | in_uint8(s, type); 305 | in_uint8(s, flags); 306 | in_uint16(s, length); 307 | in_uint32(s, data); 308 | 309 | if (type == RDP_NEG_FAILURE) 310 | { 311 | RD_BOOL retry_without_neg = False; 312 | 313 | switch (data) 314 | { 315 | case SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER: 316 | reason = "SSL with user authentication required by server"; 317 | break; 318 | case SSL_NOT_ALLOWED_BY_SERVER: 319 | reason = "SSL not allowed by server"; 320 | retry_without_neg = True; 321 | break; 322 | case SSL_CERT_NOT_ON_SERVER: 323 | reason = "no valid authentication certificate on server"; 324 | retry_without_neg = True; 325 | break; 326 | case INCONSISTENT_FLAGS: 327 | reason = "inconsistent negotiation flags"; 328 | break; 329 | case SSL_REQUIRED_BY_SERVER: 330 | reason = "SSL required by server"; 331 | break; 332 | case HYBRID_REQUIRED_BY_SERVER: 333 | /* [CVE-2019-0708] I'm told when this is the case, then the 334 | * target is not vulnerable */ 335 | reason = "CredSSP/NLA required by server"; 336 | STATUS(1, "[-] negotiate fail: %s\n", reason); 337 | RESULT("SAFE - CredSSP/NLA required\n"); 338 | break; 339 | default: 340 | reason = "unknown reason"; 341 | } 342 | 343 | tcp_disconnect(); 344 | 345 | if (retry_without_neg) 346 | { 347 | STATUS(1, "[-] negotiate fail: wrong protocol, retrying with plain RDP.\n"); 348 | g_negotiate_rdp_protocol = False; 349 | goto retry; 350 | } 351 | 352 | STATUS(0, "[-] negotiate fail: %s\n", reason); 353 | return False; 354 | } 355 | 356 | if (type != RDP_NEG_RSP) 357 | { 358 | tcp_disconnect(); 359 | error("Expected RDP_NEG_RSP, got type = 0x%x\n", type); 360 | return False; 361 | } 362 | 363 | /* handle negotiation response */ 364 | if (data == PROTOCOL_SSL) 365 | { 366 | if (!tcp_tls_connect()) 367 | { 368 | /* failed to connect using cssp, let retry with plain TLS */ 369 | tcp_disconnect(); 370 | neg_proto = PROTOCOL_RDP; 371 | goto retry; 372 | } 373 | /* do not use encryption when using TLS */ 374 | g_encryption = False; 375 | STATUS(1, "[+] connection established: using SSL\n", g_targetaddr, g_targetport); 376 | } 377 | #ifdef WITH_CREDSSP 378 | else if (data == PROTOCOL_HYBRID) 379 | { 380 | if (!cssp_connect(server, username, domain, password, s)) 381 | { 382 | /* failed to connect using cssp, let retry with plain TLS */ 383 | tcp_disconnect(); 384 | neg_proto = PROTOCOL_SSL; 385 | goto retry; 386 | } 387 | 388 | /* do not use encryption when using TLS */ 389 | STATUS(1, "connection established: using CredSSP.\n"); 390 | g_encryption = False; 391 | } 392 | #endif 393 | else if (data == PROTOCOL_RDP) 394 | { 395 | STATUS(1, "[+] connection established: using plain RDP.\n"); 396 | } 397 | else if (data != PROTOCOL_RDP) 398 | { 399 | tcp_disconnect(); 400 | error("Unexpected protocol in negotiation response, got data = 0x%x.\n", 401 | data); 402 | return False; 403 | } 404 | 405 | *selected_protocol = data; 406 | } 407 | return True; 408 | } 409 | 410 | /* Disconnect from the ISO layer */ 411 | void 412 | iso_disconnect(void) 413 | { 414 | iso_send_msg(ISO_PDU_DR); 415 | tcp_disconnect(); 416 | } 417 | 418 | /* reset the state to support reconnecting */ 419 | void 420 | iso_reset_state(void) 421 | { 422 | g_encryption = g_encryption_initial; 423 | tcp_reset_state(); 424 | } 425 | -------------------------------------------------------------------------------- /src/licence.c: -------------------------------------------------------------------------------- 1 | /* -*- c-basic-offset: 8 -*- 2 | rdesktop: A Remote Desktop Protocol client. 3 | RDP licensing negotiation 4 | Copyright (C) Matthew Chapman 1999-2008 5 | Copyright (C) Thomas Uhle 2011 6 | Copyright (C) Henrik Andersson 2014 7 | 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | */ 22 | #define _CRT_SECURE_NO_WARNINGS 1 23 | #include "rdesktop.h" 24 | #include "ssl.h" 25 | #include "util-xmalloc.h" 26 | #include "util-log.h" 27 | 28 | #include 29 | 30 | extern char *g_username; 31 | extern char g_hostname[16]; 32 | extern RDP_VERSION g_rdp_version; 33 | 34 | static uint8 g_licence_key[16]; 35 | static uint8 g_licence_sign_key[16]; 36 | 37 | RD_BOOL g_licence_issued = False; 38 | RD_BOOL g_licence_error_result = False; 39 | 40 | /* Generate a session key and RC4 keys, given client and server randoms */ 41 | static void 42 | licence_generate_keys(uint8 * client_random, uint8 * server_random, uint8 * pre_master_secret) 43 | { 44 | uint8 master_secret[48]; 45 | uint8 key_block[48]; 46 | 47 | /* Generate master secret and then key material */ 48 | sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A'); 49 | sec_hash_48(key_block, master_secret, server_random, client_random, 'A'); 50 | 51 | /* Store first 16 bytes of session key as MAC secret */ 52 | memcpy(g_licence_sign_key, key_block, 16); 53 | 54 | /* Generate RC4 key from next 16 bytes */ 55 | sec_hash_16(g_licence_key, &key_block[16], client_random, server_random); 56 | } 57 | 58 | static void 59 | licence_generate_hwid(uint8 * hwid) 60 | { 61 | buf_out_uint32(hwid, 2); 62 | strncpy((char *) (hwid + 4), g_hostname, LICENCE_HWID_SIZE - 4); 63 | } 64 | 65 | /* Send a lincece info packet to server */ 66 | static void 67 | licence_info(uint8 * client_random, uint8 * rsa_data, 68 | uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature) 69 | { 70 | uint32 sec_flags = SEC_LICENCE_NEG; 71 | uint16 length = 72 | 24 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE + 73 | licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE; 74 | STREAM s; 75 | 76 | s = sec_init(sec_flags, length + 2); 77 | 78 | out_uint8(s, LICENCE_TAG_LICENCE_INFO); 79 | out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */ 80 | out_uint16_le(s, length); 81 | 82 | out_uint32_le(s, 1); 83 | out_uint16(s, 0); 84 | out_uint16_le(s, 0x0201); 85 | 86 | out_uint8p(s, client_random, SEC_RANDOM_SIZE); 87 | out_uint16_le(s, 2); 88 | out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE)); 89 | out_uint8p(s, rsa_data, SEC_MODULUS_SIZE); 90 | out_uint8s(s, SEC_PADDING_SIZE); 91 | 92 | out_uint16_le(s, 1); 93 | out_uint16_le(s, licence_size); 94 | out_uint8p(s, licence_data, licence_size); 95 | 96 | out_uint16_le(s, 1); 97 | out_uint16_le(s, LICENCE_HWID_SIZE); 98 | out_uint8p(s, hwid, LICENCE_HWID_SIZE); 99 | 100 | out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE); 101 | 102 | s_mark_end(s); 103 | sec_send(s, sec_flags); 104 | } 105 | 106 | /* Send a new licence request packet */ 107 | static void 108 | licence_send_new_licence_request(uint8 * client_random, uint8 * rsa_data, char *user, char *host) 109 | { 110 | uint32 sec_flags = SEC_LICENCE_NEG; 111 | uint16 userlen = (uint16)strlen(user) + 1; 112 | uint16 hostlen = (uint16)strlen(host) + 1; 113 | uint16 length = 114 | 24 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE + userlen + hostlen; 115 | STREAM s; 116 | 117 | s = sec_init(sec_flags, length + 2); 118 | 119 | out_uint8(s, LICENCE_TAG_NEW_LICENCE_REQUEST); 120 | out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */ 121 | out_uint16_le(s, length); 122 | 123 | out_uint32_le(s, 1); // KEY_EXCHANGE_ALG_RSA 124 | out_uint16(s, 0); 125 | out_uint16_le(s, 0xff01); 126 | 127 | out_uint8p(s, client_random, SEC_RANDOM_SIZE); 128 | out_uint16_le(s, 2); 129 | out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE)); 130 | out_uint8p(s, rsa_data, SEC_MODULUS_SIZE); 131 | out_uint8s(s, SEC_PADDING_SIZE); 132 | 133 | /* Username LICENSE_BINARY_BLOB */ 134 | out_uint16_le(s, BB_CLIENT_USER_NAME_BLOB); 135 | out_uint16_le(s, userlen); 136 | out_uint8p(s, user, userlen); 137 | 138 | /* Machinename LICENSE_BINARY_BLOB */ 139 | out_uint16_le(s, BB_CLIENT_MACHINE_NAME_BLOB); 140 | out_uint16_le(s, hostlen); 141 | out_uint8p(s, host, hostlen); 142 | 143 | s_mark_end(s); 144 | sec_send(s, sec_flags); 145 | } 146 | 147 | /* Process a licence request packet */ 148 | static void 149 | licence_process_request(STREAM s) 150 | { 151 | uint8 null_data[SEC_MODULUS_SIZE]; 152 | uint8 *server_random; 153 | uint8 signature[LICENCE_SIGNATURE_SIZE]; 154 | uint8 hwid[LICENCE_HWID_SIZE]; 155 | uint8 *licence_data; 156 | int licence_size; 157 | RDSSL_RC4 crypt_key; 158 | 159 | /* Retrieve the server random from the incoming packet */ 160 | in_uint8p(s, server_random, SEC_RANDOM_SIZE); 161 | 162 | /* We currently use null client keys. This is a bit naughty but, hey, 163 | the security of licence negotiation isn't exactly paramount. */ 164 | memset(null_data, 0, sizeof(null_data)); 165 | licence_generate_keys(null_data, server_random, null_data); 166 | 167 | licence_size = load_licence(&licence_data); 168 | if (licence_size > 0) 169 | { 170 | /* Generate a signature for the HWID buffer */ 171 | licence_generate_hwid(hwid); 172 | sec_sign(signature, 16, g_licence_sign_key, 16, hwid, sizeof(hwid)); 173 | 174 | /* Now encrypt the HWID */ 175 | rdssl_rc4_set_key(&crypt_key, g_licence_key, 16); 176 | rdssl_rc4_crypt(&crypt_key, hwid, hwid, sizeof(hwid)); 177 | 178 | #if WITH_DEBUG 179 | DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_LICENCE_INFO)); 180 | #endif 181 | licence_info(null_data, null_data, licence_data, licence_size, hwid, signature); 182 | 183 | xfree(licence_data); 184 | return; 185 | } 186 | 187 | #if WITH_DEBUG 188 | DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_NEW_LICENCE_REQUEST)); 189 | #endif 190 | licence_send_new_licence_request(null_data, null_data, g_username, g_hostname); 191 | } 192 | 193 | /* Send a platform challange response packet */ 194 | static void 195 | licence_send_platform_challange_response(uint8 * token, uint8 * crypt_hwid, uint8 * signature) 196 | { 197 | uint32 sec_flags = SEC_LICENCE_NEG; 198 | uint16 length = 58; 199 | STREAM s; 200 | 201 | s = sec_init(sec_flags, length + 2); 202 | 203 | out_uint8(s, LICENCE_TAG_PLATFORM_CHALLANGE_RESPONSE); 204 | out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */ 205 | out_uint16_le(s, length); 206 | 207 | out_uint16_le(s, 1); 208 | out_uint16_le(s, LICENCE_TOKEN_SIZE); 209 | out_uint8p(s, token, LICENCE_TOKEN_SIZE); 210 | 211 | out_uint16_le(s, 1); 212 | out_uint16_le(s, LICENCE_HWID_SIZE); 213 | out_uint8p(s, crypt_hwid, LICENCE_HWID_SIZE); 214 | 215 | out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE); 216 | 217 | s_mark_end(s); 218 | sec_send(s, sec_flags); 219 | } 220 | 221 | /* Parse an platform challange request packet */ 222 | static RD_BOOL 223 | licence_parse_platform_challange(STREAM s, uint8 ** token, uint8 ** signature) 224 | { 225 | uint16 tokenlen; 226 | 227 | in_uint8s(s, 6); /* unknown: f8 3d 15 00 04 f6 */ 228 | 229 | in_uint16_le(s, tokenlen); 230 | if (tokenlen != LICENCE_TOKEN_SIZE) 231 | { 232 | error("token len %d\n", tokenlen); 233 | return False; 234 | } 235 | 236 | in_uint8p(s, *token, tokenlen); 237 | in_uint8p(s, *signature, LICENCE_SIGNATURE_SIZE); 238 | 239 | return s_check_end(s); 240 | } 241 | 242 | /* Process a platform challange packet */ 243 | static void 244 | licence_process_platform_challange(STREAM s) 245 | { 246 | uint8 *in_token = NULL, *in_sig; 247 | uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE]; 248 | uint8 hwid[LICENCE_HWID_SIZE], crypt_hwid[LICENCE_HWID_SIZE]; 249 | uint8 sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE]; 250 | uint8 out_sig[LICENCE_SIGNATURE_SIZE]; 251 | RDSSL_RC4 crypt_key; 252 | 253 | /* Parse incoming packet and save the encrypted token */ 254 | licence_parse_platform_challange(s, &in_token, &in_sig); 255 | memcpy(out_token, in_token, LICENCE_TOKEN_SIZE); 256 | 257 | /* Decrypt the token. It should read TEST in Unicode. */ 258 | rdssl_rc4_set_key(&crypt_key, g_licence_key, 16); 259 | rdssl_rc4_crypt(&crypt_key, in_token, decrypt_token, LICENCE_TOKEN_SIZE); 260 | 261 | /* Generate a signature for a buffer of token and HWID */ 262 | licence_generate_hwid(hwid); 263 | memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE); 264 | memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE); 265 | sec_sign(out_sig, 16, g_licence_sign_key, 16, sealed_buffer, sizeof(sealed_buffer)); 266 | 267 | /* Now encrypt the HWID */ 268 | rdssl_rc4_set_key(&crypt_key, g_licence_key, 16); 269 | rdssl_rc4_crypt(&crypt_key, hwid, crypt_hwid, LICENCE_HWID_SIZE); 270 | 271 | licence_send_platform_challange_response(out_token, crypt_hwid, out_sig); 272 | } 273 | 274 | /* Process a new licence packet */ 275 | static void 276 | licence_process_new_license(STREAM s) 277 | { 278 | RDSSL_RC4 crypt_key; 279 | uint32 length; 280 | int i; 281 | 282 | in_uint8s(s, 2); // Skip license binary blob type 283 | in_uint16_le(s, length); 284 | if (!s_check_rem(s, length)) 285 | return; 286 | 287 | rdssl_rc4_set_key(&crypt_key, g_licence_key, 16); 288 | rdssl_rc4_crypt(&crypt_key, s->p, s->p, length); 289 | 290 | /* Parse NEW_LICENSE_INFO block */ 291 | in_uint8s(s, 4); // skip dwVersion 292 | 293 | /* Skip strings, Scope, CompanyName and ProductId to get 294 | to the LicenseInfo which we store in license blob. */ 295 | length = 0; 296 | for (i = 0; i < 4; i++) 297 | { 298 | in_uint8s(s, length); 299 | in_uint32_le(s, length); 300 | if (!s_check_rem(s, length)) 301 | return; 302 | } 303 | 304 | g_licence_issued = True; 305 | save_licence(s->p, length); 306 | } 307 | 308 | /* process a licence error alert packet */ 309 | void 310 | licence_process_error_alert(STREAM s) 311 | { 312 | uint32 error_code; 313 | uint32 state_transition; 314 | uint32 error_info; 315 | in_uint32(s, error_code); 316 | in_uint32(s, state_transition); 317 | in_uint32(s, error_info); 318 | 319 | /* There is a special case in the error alert handling, when licensing is all good 320 | and the server is not sending a license to client, a "Server License Error PDU - 321 | Valid Client" packet is sent which means, every thing is ok. 322 | 323 | Therefor we should flag that everything is ok with license here. 324 | */ 325 | if (error_code == 0x07) 326 | { 327 | g_licence_issued = True; 328 | return; 329 | } 330 | 331 | /* handle error codes, for now, jsut report them */ 332 | switch (error_code) 333 | { 334 | case 0x6: // ERR_NO_LICENSE_SERVER 335 | warning("License error alert from server: No license server\n"); 336 | break; 337 | 338 | case 0x8: // ERR_INVALID_CLIENT 339 | warning("License error alert from server: Invalid client\n"); 340 | break; 341 | 342 | case 0x4: // ERR_INVALID_SCOPE 343 | case 0xb: // ERR_INVALID_PRODUCTID 344 | case 0xc: // ERR_INVALID_MESSAGE_LENGTH 345 | default: 346 | warning("License error alert from server: code %u, state transition %u\n", 347 | error_code, state_transition); 348 | break; 349 | } 350 | 351 | g_licence_error_result = True; 352 | } 353 | 354 | 355 | /* Process a licence packet */ 356 | void 357 | licence_process(STREAM s) 358 | { 359 | uint8 tag; 360 | 361 | in_uint8(s, tag); 362 | in_uint8s(s, 3); /* version, length */ 363 | 364 | #if WITH_DEBUG 365 | DEBUG(("Received licensing PDU (message type 0x%02x)\n", tag)); 366 | #endif 367 | 368 | switch (tag) 369 | { 370 | case LICENCE_TAG_REQUEST: 371 | licence_process_request(s); 372 | break; 373 | 374 | case LICENCE_TAG_PLATFORM_CHALLANGE: 375 | licence_process_platform_challange(s); 376 | break; 377 | 378 | case LICENCE_TAG_NEW_LICENCE: 379 | case LICENCE_TAG_UPGRADE_LICENCE: 380 | /* we can handle new and upgrades of licences the same way. */ 381 | licence_process_new_license(s); 382 | break; 383 | 384 | case LICENCE_TAG_ERROR_ALERT: 385 | licence_process_error_alert(s); 386 | break; 387 | 388 | default: 389 | unimpl("licence tag 0x%02x\n", tag); 390 | } 391 | } 392 | -------------------------------------------------------------------------------- /src/constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | rdesktop: A Remote Desktop Protocol client. 3 | Miscellaneous protocol constants 4 | Copyright (C) Matthew Chapman 1999-2008 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | #ifndef RDESK_CONSTANTS_H 20 | #define RDESK_CONSTANTS_H 21 | 22 | 23 | #define DEFAULT_CODEPAGE "UTF-8" 24 | #define WINDOWS_CODEPAGE "UTF-16LE" 25 | 26 | /* ISO PDU codes */ 27 | enum ISO_PDU_CODE 28 | { 29 | ISO_PDU_CR = 0xE0, /* Connection Request */ 30 | ISO_PDU_CC = 0xD0, /* Connection Confirm */ 31 | ISO_PDU_DR = 0x80, /* Disconnect Request */ 32 | ISO_PDU_DT = 0xF0, /* Data */ 33 | ISO_PDU_ER = 0x70 /* Error */ 34 | }; 35 | 36 | /* RDP protocol negotiating constants */ 37 | enum RDP_NEG_TYPE_CODE 38 | { 39 | RDP_NEG_REQ = 1, 40 | RDP_NEG_RSP = 2, 41 | RDP_NEG_FAILURE = 3 42 | }; 43 | 44 | enum RDP_NEG_REQ_CODE 45 | { 46 | PROTOCOL_RDP = 0, 47 | PROTOCOL_SSL = 1, 48 | PROTOCOL_HYBRID = 2 49 | }; 50 | 51 | enum RDP_NEG_FAILURE_CODE 52 | { 53 | SSL_REQUIRED_BY_SERVER = 1, 54 | SSL_NOT_ALLOWED_BY_SERVER = 2, 55 | SSL_CERT_NOT_ON_SERVER = 3, 56 | INCONSISTENT_FLAGS = 4, 57 | HYBRID_REQUIRED_BY_SERVER = 5, 58 | SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER = 6 59 | }; 60 | 61 | /* MCS PDU codes */ 62 | enum MCS_PDU_TYPE 63 | { 64 | MCS_EDRQ = 1, /* Erect Domain Request */ 65 | MCS_DPUM = 8, /* Disconnect Provider Ultimatum */ 66 | MCS_AURQ = 10, /* Attach User Request */ 67 | MCS_AUCF = 11, /* Attach User Confirm */ 68 | MCS_CJRQ = 14, /* Channel Join Request */ 69 | MCS_CJCF = 15, /* Channel Join Confirm */ 70 | MCS_SDRQ = 25, /* Send Data Request */ 71 | MCS_SDIN = 26 /* Send Data Indication */ 72 | }; 73 | 74 | #define MCS_CONNECT_INITIAL 0x7f65 75 | #define MCS_CONNECT_RESPONSE 0x7f66 76 | 77 | #define BER_TAG_BOOLEAN 1 78 | #define BER_TAG_INTEGER 2 79 | #define BER_TAG_OCTET_STRING 4 80 | #define BER_TAG_RESULT 10 81 | #define BER_TAG_SEQUENCE 16 82 | #define BER_TAG_CONSTRUCTED 0x20 83 | #define BER_TAG_CTXT_SPECIFIC 0x80 84 | 85 | #define MCS_TAG_DOMAIN_PARAMS 0x30 86 | 87 | #define MCS_GLOBAL_CHANNEL 1003 88 | #define MCS_USERCHANNEL_BASE 1001 89 | 90 | /* RDP secure transport constants */ 91 | #define SEC_RANDOM_SIZE 32 92 | #define SEC_MODULUS_SIZE 64 93 | #define SEC_MAX_MODULUS_SIZE 256 94 | #define SEC_PADDING_SIZE 8 95 | #define SEC_EXPONENT_SIZE 4 96 | 97 | #define SEC_CLIENT_RANDOM 0x0001 98 | #define SEC_ENCRYPT 0x0008 99 | #define SEC_LOGON_INFO 0x0040 100 | #define SEC_LICENCE_NEG 0x0080 101 | #define SEC_REDIRECT_ENCRYPT 0x0C00 102 | 103 | #define SEC_TAG_SRV_INFO 0x0c01 104 | #define SEC_TAG_SRV_CRYPT 0x0c02 105 | #define SEC_TAG_SRV_CHANNELS 0x0c03 106 | 107 | #define SEC_TAG_CLI_INFO 0xc001 108 | #define SEC_TAG_CLI_CRYPT 0xc002 109 | #define SEC_TAG_CLI_CHANNELS 0xc003 110 | #define SEC_TAG_CLI_CLUSTER 0xc004 111 | 112 | #define SEC_TAG_PUBKEY 0x0006 113 | #define SEC_TAG_KEYSIG 0x0008 114 | 115 | #define SEC_RSA_MAGIC 0x31415352 /* RSA1 */ 116 | 117 | /* Client cluster constants */ 118 | #define SEC_CC_REDIRECTION_SUPPORTED 0x00000001 119 | #define SEC_CC_REDIRECT_SESSIONID_FIELD_VALID 0x00000002 120 | #define SEC_CC_REDIRECTED_SMARTCARD 0x00000040 121 | #define SEC_CC_REDIRECT_VERSION_MASK 0x0000003c 122 | 123 | #define SEC_CC_REDIRECT_VERSION_3 0x02 124 | #define SEC_CC_REDIRECT_VERSION_4 0x03 125 | #define SEC_CC_REDIRECT_VERSION_5 0x04 126 | #define SEC_CC_REDIRECT_VERSION_6 0x05 127 | 128 | /* RDP licensing constants */ 129 | #define LICENCE_TOKEN_SIZE 10 130 | #define LICENCE_HWID_SIZE 20 131 | #define LICENCE_SIGNATURE_SIZE 16 132 | 133 | #define LICENCE_TAG_REQUEST 0x01 134 | #define LICENCE_TAG_PLATFORM_CHALLANGE 0x02 135 | #define LICENCE_TAG_NEW_LICENCE 0x03 136 | #define LICENCE_TAG_UPGRADE_LICENCE 0x04 137 | #define LICENCE_TAG_LICENCE_INFO 0x12 138 | #define LICENCE_TAG_NEW_LICENCE_REQUEST 0x13 139 | #define LICENCE_TAG_PLATFORM_CHALLANGE_RESPONSE 0x15 140 | #define LICENCE_TAG_ERROR_ALERT 0xff 141 | 142 | #define BB_CLIENT_USER_NAME_BLOB 0x000f 143 | #define BB_CLIENT_MACHINE_NAME_BLOB 0x0010 144 | 145 | /* RDP PDU codes */ 146 | enum RDP_PDU_TYPE 147 | { 148 | RDP_PDU_DEMAND_ACTIVE = 1, 149 | RDP_PDU_CONFIRM_ACTIVE = 3, 150 | RDP_PDU_REDIRECT = 4, /* Standard Server Redirect */ 151 | RDP_PDU_DEACTIVATE = 6, 152 | RDP_PDU_DATA = 7, 153 | RDP_PDU_ENHANCED_REDIRECT = 10 /* Enhanced Server Redirect */ 154 | }; 155 | 156 | enum RDP_DATA_PDU_TYPE 157 | { 158 | RDP_DATA_PDU_UPDATE = 2, 159 | RDP_DATA_PDU_CONTROL = 20, 160 | RDP_DATA_PDU_POINTER = 27, 161 | RDP_DATA_PDU_INPUT = 28, 162 | RDP_DATA_PDU_SYNCHRONISE = 31, 163 | RDP_DATA_PDU_BELL = 34, 164 | RDP_DATA_PDU_CLIENT_WINDOW_STATUS = 35, 165 | RDP_DATA_PDU_LOGON = 38, /* PDUTYPE2_SAVE_SESSION_INFO */ 166 | RDP_DATA_PDU_FONT2 = 39, 167 | RDP_DATA_PDU_KEYBOARD_INDICATORS = 41, 168 | RDP_DATA_PDU_DISCONNECT = 47, 169 | RDP_DATA_PDU_AUTORECONNECT_STATUS = 50 170 | }; 171 | 172 | enum RDP_SAVE_SESSION_PDU_TYPE 173 | { 174 | INFOTYPE_LOGON = 0, 175 | INFOTYPE_LOGON_LONG = 1, 176 | INFOTYPE_LOGON_PLAINNOTIFY = 2, 177 | INFOTYPE_LOGON_EXTENDED_INF = 3 178 | }; 179 | 180 | enum RDP_LOGON_INFO_EXTENDED_TYPE 181 | { 182 | LOGON_EX_AUTORECONNECTCOOKIE = 1, 183 | LOGON_EX_LOGONERRORS = 2 184 | }; 185 | 186 | enum RDP_CONTROL_PDU_TYPE 187 | { 188 | RDP_CTL_REQUEST_CONTROL = 1, 189 | RDP_CTL_GRANT_CONTROL = 2, 190 | RDP_CTL_DETACH = 3, 191 | RDP_CTL_COOPERATE = 4 192 | }; 193 | 194 | enum RDP_UPDATE_PDU_TYPE 195 | { 196 | RDP_UPDATE_ORDERS = 0, 197 | RDP_UPDATE_BITMAP = 1, 198 | RDP_UPDATE_PALETTE = 2, 199 | RDP_UPDATE_SYNCHRONIZE = 3 200 | }; 201 | 202 | enum RDP_POINTER_PDU_TYPE 203 | { 204 | RDP_POINTER_SYSTEM = 1, 205 | RDP_POINTER_MOVE = 3, 206 | RDP_POINTER_COLOR = 6, 207 | RDP_POINTER_CACHED = 7, 208 | RDP_POINTER_NEW = 8 209 | }; 210 | 211 | enum RDP_SYSTEM_POINTER_TYPE 212 | { 213 | RDP_NULL_POINTER = 0, 214 | RDP_DEFAULT_POINTER = 0x7F00 215 | }; 216 | 217 | enum RDP_INPUT_DEVICE 218 | { 219 | RDP_INPUT_SYNCHRONIZE = 0, 220 | RDP_INPUT_CODEPOINT = 1, 221 | RDP_INPUT_VIRTKEY = 2, 222 | RDP_INPUT_SCANCODE = 4, 223 | RDP_INPUT_MOUSE = 0x8001 224 | }; 225 | 226 | /* Device flags */ 227 | #define KBD_FLAG_RIGHT 0x0001 228 | #define KBD_FLAG_EXT 0x0100 229 | #define KBD_FLAG_QUIET 0x1000 230 | #define KBD_FLAG_DOWN 0x4000 231 | #define KBD_FLAG_UP 0x8000 232 | 233 | /* These are for synchronization; not for keystrokes */ 234 | #define KBD_FLAG_SCROLL 0x0001 235 | #define KBD_FLAG_NUMLOCK 0x0002 236 | #define KBD_FLAG_CAPITAL 0x0004 237 | 238 | /* See T.128 */ 239 | #define RDP_KEYPRESS 0 240 | #define RDP_KEYRELEASE (KBD_FLAG_DOWN | KBD_FLAG_UP) 241 | 242 | #define MOUSE_FLAG_MOVE 0x0800 243 | #define MOUSE_FLAG_BUTTON1 0x1000 244 | #define MOUSE_FLAG_BUTTON2 0x2000 245 | #define MOUSE_FLAG_BUTTON3 0x4000 246 | #define MOUSE_FLAG_BUTTON4 0x0280 247 | #define MOUSE_FLAG_BUTTON5 0x0380 248 | #define MOUSE_FLAG_DOWN 0x8000 249 | 250 | /* Raster operation masks */ 251 | #define ROP2_S(rop3) (rop3 & 0xf) 252 | #define ROP2_P(rop3) ((rop3 & 0x3) | ((rop3 & 0x30) >> 2)) 253 | 254 | #define ROP2_COPY 0xc 255 | #define ROP2_XOR 0x6 256 | #define ROP2_AND 0x8 257 | #define ROP2_NXOR 0x9 258 | #define ROP2_OR 0xe 259 | 260 | #define MIX_TRANSPARENT 0 261 | #define MIX_OPAQUE 1 262 | 263 | #define TEXT2_VERTICAL 0x04 264 | #define TEXT2_IMPLICIT_X 0x20 265 | 266 | #define ALTERNATE 1 267 | #define WINDING 2 268 | 269 | /* RDP bitmap cache (version 2) constants */ 270 | #define BMPCACHE2_C0_CELLS 0x78 271 | #define BMPCACHE2_C1_CELLS 0x78 272 | #define BMPCACHE2_C2_CELLS 0x150 273 | #define BMPCACHE2_NUM_PSTCELLS 0x9f6 274 | 275 | #define PDU_FLAG_FIRST 0x01 276 | #define PDU_FLAG_LAST 0x02 277 | 278 | /* RDP capabilities */ 279 | #define RDP_CAPSET_GENERAL 1 /* Maps to generalCapabilitySet in T.128 page 138 */ 280 | #define RDP_CAPLEN_GENERAL 0x18 281 | #define OS_MAJOR_TYPE_UNIX 4 282 | #define OS_MINOR_TYPE_XSERVER 7 283 | 284 | #define RDP_CAPSET_BITMAP 2 285 | #define RDP_CAPLEN_BITMAP 0x1C 286 | 287 | #define RDP_CAPSET_ORDER 3 288 | #define RDP_CAPLEN_ORDER 0x58 289 | #define ORDER_CAP_NEGOTIATE 2 290 | #define ORDER_CAP_NOSUPPORT 4 291 | 292 | #define RDP_CAPSET_BMPCACHE 4 293 | #define RDP_CAPLEN_BMPCACHE 0x28 294 | 295 | #define RDP_CAPSET_CONTROL 5 296 | #define RDP_CAPLEN_CONTROL 0x0C 297 | 298 | #define RDP_CAPSET_ACTIVATE 7 299 | #define RDP_CAPLEN_ACTIVATE 0x0C 300 | 301 | #define RDP_CAPSET_POINTER 8 302 | #define RDP_CAPLEN_POINTER 0x08 303 | #define RDP_CAPLEN_NEWPOINTER 0x0a 304 | 305 | #define RDP_CAPSET_SHARE 9 306 | #define RDP_CAPLEN_SHARE 0x08 307 | 308 | #define RDP_CAPSET_COLCACHE 10 309 | #define RDP_CAPLEN_COLCACHE 0x08 310 | 311 | #define RDP_CAPSET_BRUSHCACHE 15 312 | #define RDP_CAPLEN_BRUSHCACHE 0x08 313 | 314 | #define RDP_CAPSET_BMPCACHE2 19 315 | #define RDP_CAPLEN_BMPCACHE2 0x28 316 | #define BMPCACHE2_FLAG_PERSIST ((uint32)1<<31) 317 | 318 | #define RDP_SOURCE "MSTSC" 319 | 320 | /* Logon flags */ 321 | #define RDP_INFO_MOUSE 0x00000001 322 | #define RDP_INFO_DISABLECTRLALTDEL 0x00000002 323 | #define RDP_INFO_AUTOLOGON 0x00000008 324 | #define RDP_INFO_UNICODE 0x00000010 325 | #define RDP_INFO_MAXIMIZESHELL 0x00000020 326 | #define RDP_INFO_COMPRESSION 0x00000080 /* mppc compression with 8kB histroy buffer */ 327 | #define RDP_INFO_ENABLEWINDOWSKEY 0x00000100 328 | #define RDP_INFO_COMPRESSION2 0x00000200 /* rdp5 mppc compression with 64kB history buffer */ 329 | #define RDP_INFO_REMOTE_CONSOLE_AUDIO 0x00002000 330 | #define RDP_INFO_PASSWORD_IS_SC_PIN 0x00040000 331 | 332 | #define RDP5_DISABLE_NOTHING 0x00 333 | #define RDP5_NO_WALLPAPER 0x01 334 | #define RDP5_NO_FULLWINDOWDRAG 0x02 335 | #define RDP5_NO_MENUANIMATIONS 0x04 336 | #define RDP5_NO_THEMING 0x08 337 | #define RDP5_NO_CURSOR_SHADOW 0x20 338 | #define RDP5_NO_CURSORSETTINGS 0x40 /* disables cursor blinking */ 339 | 340 | /* compression types */ 341 | #define RDP_MPPC_BIG 0x01 342 | #define RDP_MPPC_COMPRESSED 0x20 343 | #define RDP_MPPC_RESET 0x40 344 | #define RDP_MPPC_FLUSH 0x80 345 | #define RDP_MPPC_DICT_SIZE 65536 346 | 347 | #define RDP5_COMPRESSED 0x80 348 | 349 | /* Keymap flags */ 350 | #define MapRightShiftMask (1<<0) 351 | #define MapLeftShiftMask (1<<1) 352 | #define MapShiftMask (MapRightShiftMask | MapLeftShiftMask) 353 | 354 | #define MapRightAltMask (1<<2) 355 | #define MapLeftAltMask (1<<3) 356 | #define MapAltGrMask MapRightAltMask 357 | 358 | #define MapRightCtrlMask (1<<4) 359 | #define MapLeftCtrlMask (1<<5) 360 | #define MapCtrlMask (MapRightCtrlMask | MapLeftCtrlMask) 361 | 362 | #define MapRightWinMask (1<<6) 363 | #define MapLeftWinMask (1<<7) 364 | #define MapWinMask (MapRightWinMask | MapLeftWinMask) 365 | 366 | #define MapNumLockMask (1<<8) 367 | #define MapCapsLockMask (1<<9) 368 | 369 | #define MapLocalStateMask (1<<10) 370 | 371 | #define MapInhibitMask (1<<11) 372 | 373 | #define MASK_ADD_BITS(var, mask) (var |= mask) 374 | #define MASK_REMOVE_BITS(var, mask) (var &= ~mask) 375 | #define MASK_HAS_BITS(var, mask) ((var & mask)>0) 376 | #define MASK_CHANGE_BIT(var, mask, active) (var = ((var & ~mask) | (active ? mask : 0))) 377 | 378 | /* Clipboard constants, "borrowed" from GCC system headers in 379 | the w32 cross compiler 380 | this is the CF_ set when WINVER is 0x0400 */ 381 | 382 | #ifndef CF_TEXT 383 | #define CF_TEXT 1 384 | #define CF_BITMAP 2 385 | #define CF_METAFILEPICT 3 386 | #define CF_SYLK 4 387 | #define CF_DIF 5 388 | #define CF_TIFF 6 389 | #define CF_OEMTEXT 7 390 | #define CF_DIB 8 391 | #define CF_PALETTE 9 392 | #define CF_PENDATA 10 393 | #define CF_RIFF 11 394 | #define CF_WAVE 12 395 | #define CF_UNICODETEXT 13 396 | #define CF_ENHMETAFILE 14 397 | #define CF_HDROP 15 398 | #define CF_LOCALE 16 399 | #define CF_MAX 17 400 | #define CF_OWNERDISPLAY 128 401 | #define CF_DSPTEXT 129 402 | #define CF_DSPBITMAP 130 403 | #define CF_DSPMETAFILEPICT 131 404 | #define CF_DSPENHMETAFILE 142 405 | #define CF_PRIVATEFIRST 512 406 | #define CF_PRIVATELAST 767 407 | #define CF_GDIOBJFIRST 768 408 | #define CF_GDIOBJLAST 1023 409 | #endif 410 | 411 | /* Sound format constants */ 412 | #define WAVE_FORMAT_PCM 1 413 | #define WAVE_FORMAT_ADPCM 2 414 | #define WAVE_FORMAT_ALAW 6 415 | #define WAVE_FORMAT_MULAW 7 416 | 417 | /* Virtual channel options */ 418 | #define CHANNEL_OPTION_INITIALIZED 0x80000000 419 | #define CHANNEL_OPTION_ENCRYPT_RDP 0x40000000 420 | #define CHANNEL_OPTION_COMPRESS_RDP 0x00800000 421 | #define CHANNEL_OPTION_SHOW_PROTOCOL 0x00200000 422 | 423 | /* NT status codes for RDPDR */ 424 | #define RD_STATUS_SUCCESS 0x00000000 425 | #define RD_STATUS_NOT_IMPLEMENTED 0x00000001 426 | #define RD_STATUS_PENDING 0x00000103 427 | 428 | #define RD_STATUS_NO_MORE_FILES 0x80000006 429 | #define RD_STATUS_DEVICE_PAPER_EMPTY 0x8000000e 430 | #define RD_STATUS_DEVICE_POWERED_OFF 0x8000000f 431 | #define RD_STATUS_DEVICE_OFF_LINE 0x80000010 432 | #define RD_STATUS_DEVICE_BUSY 0x80000011 433 | 434 | #define RD_STATUS_INVALID_HANDLE 0xc0000008 435 | #define RD_STATUS_INVALID_PARAMETER 0xc000000d 436 | #define RD_STATUS_NO_SUCH_FILE 0xc000000f 437 | #define RD_STATUS_INVALID_DEVICE_REQUEST 0xc0000010 438 | #define RD_STATUS_ACCESS_DENIED 0xc0000022 439 | #define RD_STATUS_OBJECT_NAME_COLLISION 0xc0000035 440 | #define RD_STATUS_DISK_FULL 0xc000007f 441 | #define RD_STATUS_FILE_IS_A_DIRECTORY 0xc00000ba 442 | #define RD_STATUS_NOT_SUPPORTED 0xc00000bb 443 | #define RD_STATUS_TIMEOUT 0xc0000102 444 | #define RD_STATUS_NOTIFY_ENUM_DIR 0xc000010c 445 | #define RD_STATUS_CANCELLED 0xc0000120 446 | #define RD_STATUS_DIRECTORY_NOT_EMPTY 0xc0000101 447 | 448 | /* RDPSND constants */ 449 | #define TSSNDCAPS_ALIVE 0x00000001 450 | #define TSSNDCAPS_VOLUME 0x00000002 451 | 452 | /* RDPDR constants */ 453 | 454 | #define RDPDR_CTYP_CORE 0x4472 455 | #define RDPDR_CTYP_PRN 0x5052 456 | 457 | #define PAKID_CORE_SERVER_ANNOUNCE 0x496e 458 | #define PAKID_CORE_CLIENTID_CONFIRM 0x4343 459 | #define PAKID_CORE_CLIENT_NAME 0x434e 460 | #define PAKID_CORE_DEVICE_LIST_ANNOUNCE 0x4441 461 | #define PAKID_CORE_DEVICE_REPLY 0x6472 462 | #define PAKID_CORE_DEVICE_IOREQUEST 0x4952 463 | #define PAKID_CORE_DEVICE_IOCOMPLETION 0x4943 464 | #define PAKID_CORE_SERVER_CAPABILITY 0x5350 465 | #define PAKID_CORE_CLIENT_CAPABILITY 0x4350 466 | #define PAKID_CORE_DEVICELIST_REMOVE 0x444d 467 | #define PAKID_PRN_CACHE_DATA 0x5043 468 | #define PAKID_CORE_USER_LOGGEDON 0x554c 469 | #define PAKID_PRN_USING_XPS 0x5543 470 | 471 | #define RDPDR_MAX_DEVICES 0x10 472 | #define DEVICE_TYPE_SERIAL 0x01 473 | #define DEVICE_TYPE_PARALLEL 0x02 474 | #define DEVICE_TYPE_PRINTER 0x04 475 | #define DEVICE_TYPE_DISK 0x08 476 | #define DEVICE_TYPE_SCARD 0x20 477 | 478 | #define FILE_DIRECTORY_FILE 0x00000001 479 | #define FILE_NON_DIRECTORY_FILE 0x00000040 480 | #define FILE_COMPLETE_IF_OPLOCKED 0x00000100 481 | #define FILE_DELETE_ON_CLOSE 0x00001000 482 | #define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000 483 | 484 | /* RDP5 disconnect PDU */ 485 | #define exDiscReasonNoInfo 0x0000 486 | #define exDiscReasonAPIInitiatedDisconnect 0x0001 487 | #define exDiscReasonAPIInitiatedLogoff 0x0002 488 | #define exDiscReasonServerIdleTimeout 0x0003 489 | #define exDiscReasonServerLogonTimeout 0x0004 490 | #define exDiscReasonReplacedByOtherConnection 0x0005 491 | #define exDiscReasonOutOfMemory 0x0006 492 | #define exDiscReasonServerDeniedConnection 0x0007 493 | #define exDiscReasonServerDeniedConnectionFips 0x0008 494 | #define exDiscReasonServerInsufficientPrivileges 0x0009 495 | #define exDiscReasonServerFreshCredentialsRequired 0x000a 496 | #define exDiscReasonRPCInitiatedDisconnectByUser 0x000b 497 | #define exDiscReasonByUser 0x000c 498 | #define exDiscReasonLicenseInternal 0x0100 499 | #define exDiscReasonLicenseNoLicenseServer 0x0101 500 | #define exDiscReasonLicenseNoLicense 0x0102 501 | #define exDiscReasonLicenseErrClientMsg 0x0103 502 | #define exDiscReasonLicenseHwidDoesntMatchLicense 0x0104 503 | #define exDiscReasonLicenseErrClientLicense 0x0105 504 | #define exDiscReasonLicenseCantFinishProtocol 0x0106 505 | #define exDiscReasonLicenseClientEndedProtocol 0x0107 506 | #define exDiscReasonLicenseErrClientEncryption 0x0108 507 | #define exDiscReasonLicenseCantUpgradeLicense 0x0109 508 | #define exDiscReasonLicenseNoRemoteConnections 0x010a 509 | 510 | /* SeamlessRDP constants */ 511 | #define SEAMLESSRDP_NOTYETMAPPED -1 512 | #define SEAMLESSRDP_NORMAL 0 513 | #define SEAMLESSRDP_MINIMIZED 1 514 | #define SEAMLESSRDP_MAXIMIZED 2 515 | #define SEAMLESSRDP_POSITION_TIMER 200000 516 | 517 | #define SEAMLESSRDP_CREATE_MODAL 0x0001 518 | #define SEAMLESSRDP_CREATE_TOPMOST 0x0002 519 | 520 | #define SEAMLESSRDP_HELLO_RECONNECT 0x0001 521 | #define SEAMLESSRDP_HELLO_HIDDEN 0x0002 522 | 523 | /* Smartcard constants */ 524 | #define SCARD_LOCK_TCP 0 525 | #define SCARD_LOCK_SEC 1 526 | #define SCARD_LOCK_CHANNEL 2 527 | #define SCARD_LOCK_RDPDR 3 528 | #define SCARD_LOCK_LAST 4 529 | 530 | 531 | /* redirect flags, from [MS-RDPBCGR] 2.2.13.1 */ 532 | enum RDP_PDU_REDIRECT_FLAGS 533 | { 534 | PDU_REDIRECT_HAS_IP = 0x1, 535 | PDU_REDIRECT_HAS_LOAD_BALANCE_INFO = 0x2, 536 | PDU_REDIRECT_HAS_USERNAME = 0x4, 537 | PDU_REDIRECT_HAS_DOMAIN = 0x8, 538 | PDU_REDIRECT_HAS_PASSWORD = 0x10, 539 | PDU_REDIRECT_DONT_STORE_USERNAME = 0x20, 540 | PDU_REDIRECT_USE_SMARTCARD = 0x40, 541 | PDU_REDIRECT_INFORMATIONAL = 0x80, 542 | PDU_REDIRECT_HAS_TARGET_FQDN = 0x100, 543 | PDU_REDIRECT_HAS_TARGET_NETBIOS = 0x200, 544 | PDU_REDIRECT_HAS_TARGET_IP_ARRAY = 0x800 545 | }; 546 | 547 | #endif 548 | 549 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Windows download](/badges/binary-windows.svg)](https://github.com/robertdavidgraham/rdpscan/files/3242730/rdpscan-windows.zip) 2 | [![macOS download](/badges/binary-macos.svg)](https://github.com/robertdavidgraham/rdpscan/files/3240236/rdpscan-macos.zip) 3 | [![Linux download](/badges/source-linux.svg)](https://github.com/robertdavidgraham/rdpscan/archive/v0.0.2.zip) 4 | [![Follow](/badges/erratarob.svg)](https://twitter.com/intent/follow?screen_name=erratarob) 5 | [![Build](https://travis-ci.org/robertdavidgraham/rdpscan.svg?branch=master)](https://travis-ci.org/robertdavidgraham/rdpscan) 6 | 7 | # rdpscan for CVE-2019-0708 bluekeep vuln 8 | 9 | This is a quick-and-dirty scanner for the CVE-2019-0708 vulnerability in Microsoft Remote Desktop. 10 | Right now, there are about 900,000 machines on the public Internet vulnerable to this vulnerability, 11 | so many are to expect a worm soon like WannaCry and notPetya. Therefore, scan your networks and 12 | patch (or at least, enable NLA) on vulnerable systems. 13 | 14 | This is a command-line tool. You can download the source and compile it 15 | yourself, or you can download one of the pre-compiled binaries for 16 | Windows or macOS from the link above. 17 | 18 | This tool is based entirely on the `rdesktop` patch from https://github.com/zerosum0x0/CVE-2019-0708. 19 | I've simply trimmed the code so that I can easily compile on macOS and Windows, 20 | as well as added the ability to scan multiple targets. 21 | 22 | ## Status 23 | 24 | This is only a few days old and experimental. However, I am testing it by scanning 25 | the entire Internet (with the help of `masscan`, so I'm working through a lot of problems 26 | pretty quickly. You can try contacting me on twttier(@erratarob) for help/comments. 27 | 28 | - 2019-05-38 - Better output result descriptions, as well as documentation what they mean (see below). 29 | - 2019-05-27 - Windows and macOS binaries released (click on badges above). 30 | - 2019-05-26 - fixing the Windows networking issues 31 | - 2019-05-25 - Linux and macOS working well, Windows has a few network errors 32 | - 2019-05-24 - works on Linux and macOS, Windows has a few compilation bugs 33 | - 2019-05-23 - currently working on macOS within XCode 34 | 35 | ## Primary use 36 | 37 | To scan a network, run it like the following: 38 | 39 | rdpscan 192.168.1.1-192.168.1.255 40 | 41 | This produces one of 3 results for each address: 42 | - SAFE - if target has determined bot be *patched* or at least require *CredSSP/NLA* 43 | - VULNERABLE - if the target has been confirmed to be vulnerable 44 | - UNKNOWN - if the target doesn't respond or has some protocol failure 45 | 46 | When nothing exists at a target IP address, the older versions pritned the 47 | message "*UNKNOWN - connection timed out*". When scanning large networks, 48 | this produces an overload of too much information about systems you don't 49 | care about. Therefore, the new version by default doesn't produce this 50 | information unless you add *-v* (for verbose) on the command-line. 51 | 52 | You can increase the speed at which it scans large networks by increasing 53 | the number of workers: 54 | 55 | rdpscan --workers 10000 10.0.0.0/8 56 | 57 | However, on my computer, it only produces about 1500 workers, because 58 | of system limitations, no matter how high I configure this parameter. 59 | 60 | You can increase the speed even more by using this in conjunction 61 | with `masscan`, described in the second below. 62 | 63 | ## Interpreting the results 64 | 65 | There are three general responses: 66 | - *SAFE* - which means the target is probably patched or otherwise 67 | not vulnerable to the bug. 68 | - *VULNERABLE*: which means we've confirmed the target is vulnerable 69 | to this bug, and that when the worm hits, will likely get 70 | infected. 71 | - *UNKNOWN*: means we can't confirm either way, usually because 72 | the target doesn't respond or isn't running RDP, which is 73 | the vast majority of responses. Also, when targets are out 74 | of resources or experiencing network problems, we'll get 75 | a lot of these. Finally, protocol errors are responsble 76 | for a lot. 77 | While the three main responses are *SAFE*, *VULNERABLE*, and *UNKNOWN*, 78 | they contain additional text explaining the diagnosis. This section 79 | describes the various strings you'll see. 80 | 81 | ### SAFE 82 | 83 | There are three main reaons we think a target is safe: 84 | - *SAFE - Target appears patched* 85 | This happens when the target doesn't respond to the triggering 86 | request. This means it's a Windows system that's been patched, 87 | or a system that wasn't vulnerable to begin with, like Windows 10 88 | or Unix. 89 | - *SAFE - CredSSP/NLA required* 90 | This means that the target first requires Network Level Authentication before 91 | the RDP connection can be established. The tool cannot pass this point, without 92 | leigitimate credentials, so cannot determine whether the target has been patched. 93 | However, hackers can't continue past this point to exploit vulnerable systems, either, 94 | so you are likely "safe". However, when exploits appear, insiders with valid 95 | usernames/passwords will be able to exploit the system if it's un-patched. 96 | - *SAFE - not RDP* 97 | This means the system is not RDP, but has some other service that happens to use 98 | this same port, and produces a response that's clearly not RDP. Common examples are 99 | HTTP and SSH. Note however that instead of an identifiable protocol, a server 100 | may respond with a RST or FIN packet. These are identified as *UNKNOWN* instead 101 | of *SAFE*/ 102 | 103 | ### VULNERABLE 104 | 105 | This means we've confirmed the system is vulnerable to the bug. 106 | - *VULNERABLE - got appid* 107 | There is only one response when the system is vulnerable, this one. 108 | 109 | ### UNKNOWN 110 | 111 | There are a zillion variations for unknown 112 | 113 | - *UNKNOWN - no connection - timeout* 114 | This is by far the most common response, and happens when the target 115 | IP address makes no response whatsoever. In fact, it's so common that 116 | when scanning large ranges of addresses, it's usually ommited. You 117 | have to add the *-v* (verbose) flag in order to enable it. 118 | - *UNKNOWN - no connection - refused (RST)* 119 | This is by far the second most common response, and happens when 120 | the target exists and responds to network traffic, but isn't running 121 | RDP, so refuses the connection with a TCP RST packet. 122 | - *UNKNOWN - RDP protocol error - receive timeout* 123 | This is the third most common response, and happens when we've successfully 124 | established an RDP connection, but then the server stops responding 125 | to us. This is due to network errors and when the target system is 126 | overloaded for some reason. It could also be network errors on this 127 | end, such as when you are behind a NAT and overloading it with too 128 | many connections. 129 | - *UNKNOWN - no connection - connection closed* 130 | This means we've established a connection (TCP SYN-ACK), but then 131 | the connection is immediately closed (with a RST or FIN). There are 132 | many reasons this happen, which we cannot distinguish: 133 | - It's running RDP, but for some reason closes the connection, 134 | possibly because it's out-of-resources. 135 | - It's not RDP, and doesn't like the RDP request we send it, 136 | so instad of sending us a nice error message (which would 137 | trigger *SAFE - not RDP*), it abruptly closes the connection. 138 | - Some intervening device, like an IPS, firewall, or NAT closed 139 | the connection because it identified this as hostile, or 140 | ran out of resources. 141 | - Some other reason I haven't identified, there's a lot of 142 | weird stuff happening when I scan the Internet. 143 | - *UNKNOWN - no connection - host unreachable (ICMP error)* 144 | The remote network reports the host cannot be reached or is not running. 145 | Try again later if you think that host should be alive. 146 | - *UNKNOWN - no connection - network unreachable (ICMP error)* 147 | There is a (transient) network error on the far end, try again 148 | later if you believe that network should be running. 149 | - *UNKNOWN - RDP protocol error* 150 | This means some corruption happened in the RDP protocol, either because 151 | the remote side implents it wrong (not a Windows system), because it's 152 | handling a transient network error badly, or something else. 153 | - *UNKNOWN - SSL protocol error* 154 | Since Windows Vista, RDP uses the STARTTLS protocol to run over SSL. 155 | This layer has it's own problems like above, which includes handling 156 | underlying network errors badly, or trying to communicate with 157 | systems that have some sort of incompatibility. If you get a very 158 | long error message here (like SSL3_GET_RECORD:wrong version), it's 159 | because the other side has a bug in SSL, or your own SSL library that 160 | you are using has a bug. 161 | 162 | 163 | ## Using with masscan 164 | 165 | This `rdpscan` tool is fairly slow, only scanning a few hundred targets per second. 166 | You can instead use [`masscan`](https://github.com/robertdavidgraham/masscan) to speed things up. 167 | The `masscan` tool is roughly 1000 times faster, but only gives limited information 168 | on the target. 169 | 170 | The steps are: 171 | * First scan the address ranges with masscan to quickly find hosts that 172 | respond on port 3389 (or whatever port you use). 173 | * Second feed the output of `masscan` into `rdpscan`, so it only has 174 | to scan targets we know are active. 175 | 176 | The simple way to run this is just to combine them on the command-line: 177 | 178 | masscan 10.0.0.0/8 -p3389 | rdpscan --file - 179 | 180 | The way I do it is in two steps: 181 | 182 | masscan 10.0.0.0/8 -p3389 > ips.txt 183 | rdpscan --file ips.txt --workers 10000 >results.txt 184 | 185 | 186 | ## Building 187 | 188 | The difficult part is getting the *OpenSSL* libraries installed, and not conflicting 189 | with other versions on the system. Some examples for versions of Linux I've tested on 190 | are the following, but they keep changing package names from one distribution to 191 | the next. Also, there are many options for an OpenSSL-compatible API, such as BoringSSL 192 | and LibreSSL. 193 | 194 | $ sudo apt install libssl-dev 195 | $ sudo yum install openssl-devel 196 | 197 | Once you've solved that problem, you just compile all the `.c` files together 198 | like this: 199 | 200 | $ gcc *.c -lssl -lcrypto -o rdpscan 201 | 202 | I've put a Makefile in the directory that does this, so you can likely do 203 | just: 204 | 205 | $ make 206 | 207 | The code is written in C, so needs a C compiler installed, such as doing the following: 208 | 209 | $ sudo apt install build-essential 210 | 211 | ## Common build errors 212 | 213 | This section describes the more obvious build errors. 214 | 215 | ssl.h:24:25: fatal error: openssl/rc4.h: No such file or directory 216 | 217 | This means you either don't have the OpensSSL headers installed, or they aren't 218 | in a path somewhere. Remember that even if you have OpenSSL binaries installed, 219 | this doesn't mean you've got the development stuff installed. You need both 220 | the headers and libraries installed. 221 | 222 | To install these things on Debian, do: 223 | 224 | $ sudo apt install libssl-dev 225 | 226 | To fix the path issue, add a compilation flag `-I/usr/local/include`, or something 227 | similar. 228 | 229 | An example linker problem is the following: 230 | 231 | Undefined symbols for architecture x86_64: 232 | "_OPENSSL_init_ssl", referenced from: 233 | _tcp_tls_connect in tcp-fac73c.o 234 | "_RSA_get0_key", referenced from: 235 | _rdssl_rkey_get_exp_mod in ssl-d5fdf5.o 236 | "_SSL_CTX_set_options", referenced from: 237 | _tcp_tls_connect in tcp-fac73c.o 238 | "_X509_get_X509_PUBKEY", referenced from: 239 | _rdssl_cert_to_rkey in ssl-d5fdf5.o 240 | 241 | I get this on macOS because there's multiple versions of OpenSSL. I fix this 242 | by hard-coding the paths: 243 | 244 | $ gcc *.c -lssl -lcrypto -I/usr/local/include -L/usr/local/lib -o rdpscan 245 | 246 | According to comments by others, the following command-line might work on macOS 247 | if you've used Homebrew to install things. I still get the linking errors above, though, 248 | because I've installed other OpenSSL components that are conflicting. 249 | 250 | gcc $(brew --prefix)/opt/openssl/lib/libssl.a $(brew --prefix)/opt/openssl/lib/libcrypto.a -o rdpscan *.c 251 | 252 | 253 | ## Running 254 | 255 | The section above gives quickstart tips for running the program. This section gives 256 | more in-depth help. 257 | 258 | To scan a single target, just pass the address of the target: 259 | 260 | ./rdpscan 192.168.10.101 261 | 262 | You can pass in IPv6 addresses and DNS names. You can pass in multiple targets. 263 | An example of this would be: 264 | 265 | ./rdpscan 192.168.10.101 exchange.example.com 2001:0db8:85a3::1 266 | 267 | You can also scan ranges of addresses, using either begin-end IPv4 addresses, 268 | or IPv4 CIDR spec. IPv6 ranges aren't supported because they are so big. 269 | 270 | ./rdpscan 10.0.0.1-10.0.0.25 192.168.0.0/16 271 | 272 | By default, it scans only 100 targets at a time. You can increase this number 273 | with the `--workers` parameter. However, no matter how high you set this 274 | parameter, in practice you'll get a max of around 500 to 1500 workers running 275 | at once, depending upon your system. 276 | 277 | ./rdpscan --workers 1000 10.0.0.0/24 278 | 279 | Instead of specifying targets on the command-line, you can load them 280 | from a file instead, using the well-named `--file` parameter: 281 | 282 | ./rdpscan --file ips.txt 283 | 284 | The format of the file is one address, name, or range per line. It can also 285 | consume the text generated by `masscan`. Extra whitespace is trimmed, 286 | blank lines ignored, any any comment lines are ignored. A *comment* is 287 | a line starting with the `#` character, or `//` characters. 288 | 289 | The output is sent to `stdout` giving the status of VULNERABLE, SAFE, 290 | or UNKNOWN. There could be additional reasons for each. These reasons 291 | are described above. 292 | 293 | 211.101.37.250 - SAFE - CredSSP/NLA required 294 | 185.11.124.79 - SAFE - not RDP - SSH response seen 295 | 125.121.137.42 - UNKNOWN - no connection - refused (RST) 296 | 40.117.191.215 - SAFE - CredSSP/NLA required 297 | 121.204.186.182 - SAFE - CredSSP/NLA required 298 | 99.8.11.148 - SAFE - CredSSP/NLA required 299 | 121.204.186.114 - SAFE - CredSSP/NLA required 300 | 49.50.145.236 - SAFE - CredSSP/NLA required 301 | 106.12.74.155 - VULNERABLE - got appid 302 | 222.84.253.26 - SAFE - CredSSP/NLA required 303 | 144.35.133.109 - UNKNOWN - RDP protocol error - receive timeout 304 | 199.212.226.196 - UNKNOWN - RDP protocol error - receive timeout 305 | 183.134.58.152 - UNKNOWN - no connection - refused (RST) 306 | 83.162.246.149 - VULNERABLE - got appid 307 | 308 | You can process this with additional unix commands like `grep` and `cut`. 309 | To get a list of just vulnerable machines: 310 | 311 | ./rdpscan 10.0.0.0/8 | grep 'VULN' | cut -f1 -d'-' 312 | 313 | The parameter `-dddd` means *diagnostic* information, where the more `d`s you 314 | add, the more details are printed. This is sent to `stderr` instead of `stdout` 315 | so that you can separate the streams. Using `bash` this is done like this: 316 | 317 | ./rdpscan --file myips.txt -ddd 2> diag.txt 1> results.txt 318 | 319 | 320 | ## Diagnostic info 321 | 322 | Adding the `-d` parameter dumps diagnostic info on the connections to `stderr`. 323 | 324 | ./rdpscan 62.15.34.157 -d 325 | 326 | [+] [62.15.34.157]:3389 - connecting... 327 | [+] [62.15.34.157]:3389 - connected from [10.1.10.133]:49211 328 | [+] [62.15.34.157]:3389 - SSL connection 329 | [+] [62.15.34.157]:3389 - version = v4.8 330 | [+] [62.15.34.157]:3389 - Sending MS_T120 check packet 331 | [-] [62.15.34.157]:3389 - Max sends reached, waiting... 332 | 62.15.34.157 - SAFE - Target appears patched 333 | 334 | On macOS/Linux, you can redirect `stdout` and `stderr` separately to different 335 | files in the usual manner: 336 | 337 | ./rdpscan --file ips.txt 2> diag.txt 1> results.txt 338 | 339 | 340 | ## SOCKS5 and Tor lulz 341 | 342 | So it includes SOCKS5 support: 343 | 344 | ./rdpscan --file ips.txt --socks5 localhost --socks5port 9050 345 | 346 | It makes connection problems worse so you get a lot more "UNKNOWN" results. 347 | 348 | ## Statically link OpenSSL 349 | 350 | For releasing the Windows and macOS binaries attached as *releases* to this project 351 | I statically link OpenSSL, so that it doesn't need to be included separately, and the 352 | programs *just work*. This section describes some notes on how to do this, especially 353 | since the description on OpenSSL's own page seems to be out of date. 354 | 355 | Both these steps start with downloading the OpenSSL source and putting 356 | it next to the `rdpscan` directory: 357 | 358 | git clone https://github.com/openssl/openssl 359 | 360 | ### Windows 361 | 362 | For Windows, you need to first install some version of Perl. I use the one 363 | from [ActiveState](http://www.activestate.com/ActivePerl). 364 | 365 | Next, you'll need a special "assembler". I use the recommended one called 366 | [NASM]( http://nasm.sourceforge.net/)) 367 | 368 | Next, you'll need a compiler. I use VisualStudio 2010. You can download 369 | the latest "Visual Studio Community Edition" (which is 2019) instead from 370 | Microsoft. 371 | 372 | Now you need to build the makefile. This is done by going into the OpenSSL 373 | directory and running the `Configure` Perl program: 374 | 375 | perl Configure VC-WIN32 376 | 377 | I chose 32-bit for Windows because there's a lot of old Windows out there, 378 | and I want to make the program as compaitble as possible with old versions. 379 | 380 | I want a completely static build, including the C runtime. To do that, I opened 381 | the resulting makefile in an editor, and changed the C compilation flag from 382 | `/MD` (meaning use DLLs) to `/MT`. While I was there, I added the following 383 | to the CPPFLAGS `-D_WIN32_WINNT=0x501`, which restrict OpenSSL to features that 384 | work back on Windows XP and Server 2003. Otherwise, you get errors that `bcrypt.dll` 385 | was not found if your run on those older systems. 386 | 387 | Now you'll need to make sure everything is in your path. I copied `nasm.exe` 388 | to the a directory in the PATH. For Visual Studio 2010, I ran the program 389 | `vcvars32.bat` to setup the path variables for the compiler. 390 | 391 | At this point on the command-line, I typed: 392 | 393 | nmake 394 | 395 | This makes the libraries. The static ones are `libssl_static.lib` and `libcrypto_static.lib`, 396 | which I use to link to in `rdpscan`. 397 | 398 | ### macOS 399 | 400 | First of all, you need to install a compiler. I use the Developer Tools from Apple, installing 401 | XCode and the compiler. I think you can use Homebrew to install `gcc` instead. 402 | 403 | Then go int othe source directory for OpenSSL and create a makefile: 404 | 405 | perl Configure darwin64-x86_64-cc 406 | 407 | Now simply make it: 408 | 409 | make depend 410 | make 411 | 412 | At this point, it's created both dynamic (`.dylib`) and static (`.lib`) libraries. I deleted 413 | the dynamic libraries so that it'll catch the static ones by default. 414 | 415 | Now in `rdpscan`, just build the macOS makefile: 416 | 417 | make -f Makefile.macos 418 | 419 | This will compile all the `rdpscan` source files, then link to the OpenSSL libraries 420 | in the directory `../openssl` that you just built. 421 | 422 | This should produce a 3-megabyte exexeutable. If you instead only got a 423 | 200-kilobyte executable, then you made a mistake and linked to the dynamic libraries 424 | instead. 425 | 426 | 427 | 428 | 429 | --------------------------------------------------------------------------------