├── .gitignore ├── LICENSE ├── README.md ├── ace_ssl ├── SSL_Asynch_BIO.cpp ├── SSL_Asynch_BIO.h ├── SSL_Asynch_Stream.cpp ├── SSL_Asynch_Stream.h ├── SSL_Asynch_Stream.inl ├── SSL_Context.cpp ├── SSL_Context.h ├── SSL_Context.inl ├── SSL_Export.h ├── SSL_SOCK.cpp ├── SSL_SOCK.h ├── SSL_SOCK.inl ├── SSL_SOCK_Acceptor.cpp ├── SSL_SOCK_Acceptor.h ├── SSL_SOCK_Acceptor.inl ├── SSL_SOCK_Connector.cpp ├── SSL_SOCK_Connector.h ├── SSL_SOCK_Connector.inl ├── SSL_SOCK_Stream.cpp ├── SSL_SOCK_Stream.h ├── SSL_SOCK_Stream.inl └── sslconf.h ├── doc ├── RDP交互过程.txt ├── The NTLM Authentication Protocol and Security Support Provider.html ├── The NTLM Authentication Protocol and Security Support Provider_files │ └── sflogo.php ├── [MS-CSSP]-13.0-20160714.pdf ├── [MS-NLMP]-28.0-20160714.pdf ├── [MS-RDPBCGR]-44.0-20170316.pdf ├── librdpp.png ├── librdpp.xmind ├── rdpmitm.png └── rdpmitm.xmind ├── librdpp ├── core │ ├── ber.h │ ├── bitmap.cpp │ ├── bitmap.h │ ├── buffer.cpp │ ├── buffer.h │ ├── config.h │ ├── crypto.cpp │ ├── crypto.h │ ├── layer.h │ ├── log.cpp │ ├── log.h │ ├── per.h │ ├── poppack.h │ ├── pshpack1.h │ ├── rss.cpp │ ├── rss.h │ ├── scancode.h │ ├── string_util.h │ ├── timestamp.cpp │ ├── timestamp.h │ └── unicode │ │ ├── README.md │ │ ├── unicode_data.h │ │ ├── unicode_data │ │ ├── UnicodeData.txt │ │ └── unicode_data_parser.py │ │ ├── utf.cpp │ │ └── utf.h ├── librdpp.vcxproj ├── librdpp.vcxproj.filters ├── librdpp.vcxproj.user └── rdp │ ├── lic.cpp │ ├── lic.h │ ├── nla │ ├── cssp.cpp │ ├── cssp.h │ ├── ntlm.cpp │ ├── ntlm.h │ └── sspi.h │ ├── pdu │ ├── caps.h │ ├── data.cpp │ ├── data.h │ ├── layer.cpp │ ├── layer.h │ └── order.h │ ├── rdp.cpp │ ├── rdp.h │ ├── sec.cpp │ ├── sec.h │ ├── t125 │ ├── certificate.cpp │ ├── certificate.h │ ├── gcc.cpp │ ├── gcc.h │ ├── mcs.cpp │ └── mcs.h │ ├── tpkt.cpp │ ├── tpkt.h │ ├── x224.cpp │ └── x224.h ├── rdpmitm ├── proxy_acceptor.cpp ├── proxy_acceptor.h ├── proxy_client.cpp ├── proxy_client.h ├── proxy_server.cpp ├── proxy_server.h ├── rdp_audit.h ├── rdpmitm.cpp ├── rdpmitm.vcxproj ├── rdpmitm.vcxproj.filters └── rdpmitm.vcxproj.user ├── rdpp.sln └── removejunk.bat /.gitignore: -------------------------------------------------------------------------------- 1 | # git ignore file 2 | bin/* 3 | ipch 4 | librdpp.orig 5 | Debug/ 6 | Release/ 7 | reference/ 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RDPP 2 | 3 | A C++ RDP implement, base RDPY 4 | 5 | ## Librdpp 6 | 7 | A C++ RDP library. 8 | 9 | ## rdpmitm 10 | 11 | A RDP Man-in-the-middle attack Tools. 12 | 13 | 14 | # Thanks 15 | 16 | https://github.com/citronneur/rdpy 17 | https://github.com/FreeRDP/FreeRDP 18 | 19 | # Contact 20 | 21 | elemeta47@gmail.com 22 | 23 | -------------------------------------------------------------------------------- /ace_ssl/SSL_Asynch_BIO.cpp: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | // $Id: SSL_Asynch_BIO.cpp 91368 2010-08-16 13:03:34Z mhengstmengel $ 3 | #include "SSL_Asynch_BIO.h" 4 | 5 | #if OPENSSL_VERSION_NUMBER > 0x0090581fL && ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS))) 6 | 7 | #include "SSL_Asynch_Stream.h" 8 | #include "ace/OS_NS_string.h" 9 | #include "ace/Truncate.h" 10 | 11 | #if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1) 12 | # define ACE_ASYNCH_BIO_WRITE_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_write) 13 | # define ACE_ASYNCH_BIO_READ_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_read) 14 | # define ACE_ASYNCH_BIO_PUTS_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_puts) 15 | # define ACE_ASYNCH_BIO_CTRL_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_ctrl) 16 | # define ACE_ASYNCH_BIO_NEW_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_new) 17 | # define ACE_ASYNCH_BIO_FREE_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_free) 18 | #else 19 | # define ACE_ASYNCH_BIO_WRITE_NAME ACE_Asynch_BIO_write 20 | # define ACE_ASYNCH_BIO_READ_NAME ACE_Asynch_BIO_read 21 | # define ACE_ASYNCH_BIO_PUTS_NAME ACE_Asynch_BIO_puts 22 | # define ACE_ASYNCH_BIO_CTRL_NAME ACE_Asynch_BIO_ctrl 23 | # define ACE_ASYNCH_BIO_NEW_NAME ACE_Asynch_BIO_new 24 | # define ACE_ASYNCH_BIO_FREE_NAME ACE_Asynch_BIO_free 25 | #endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */ 26 | 27 | /** 28 | * @name OpenSSL BIO Helper Methods for use with ACE's Asynchronous 29 | * SSL I/O support. 30 | */ 31 | //@{ 32 | extern "C" 33 | { 34 | int ACE_ASYNCH_BIO_WRITE_NAME (BIO *pBIO, const char *buf, int len); 35 | int ACE_ASYNCH_BIO_READ_NAME (BIO *pBIO, char *buf, int len); 36 | int ACE_ASYNCH_BIO_PUTS_NAME (BIO *pBIO, const char *str); 37 | long ACE_ASYNCH_BIO_CTRL_NAME (BIO *pBIO, int cmd, long arg1, void *arg2); 38 | int ACE_ASYNCH_BIO_NEW_NAME (BIO *pBIO); 39 | int ACE_ASYNCH_BIO_FREE_NAME (BIO *pBIO); 40 | } 41 | //@} 42 | 43 | #define BIO_TYPE_ACE ( 21 | BIO_TYPE_SOURCE_SINK ) 44 | 45 | static BIO_METHOD methods_ACE = 46 | { 47 | BIO_TYPE_ACE, // BIO_TYPE_PROXY_SERVER, 48 | "ACE_Asynch_BIO", 49 | ACE_ASYNCH_BIO_WRITE_NAME, 50 | ACE_ASYNCH_BIO_READ_NAME, 51 | ACE_ASYNCH_BIO_PUTS_NAME, 52 | 0, /* ACE_ASYNCH_BIO_GETS_NAME, */ 53 | ACE_ASYNCH_BIO_CTRL_NAME, 54 | ACE_ASYNCH_BIO_NEW_NAME, 55 | ACE_ASYNCH_BIO_FREE_NAME, 56 | 0 57 | }; 58 | 59 | ACE_BEGIN_VERSIONED_NAMESPACE_DECL 60 | 61 | BIO * 62 | ACE_SSL_make_BIO (void * ssl_asynch_stream) 63 | { 64 | BIO * const pBIO = BIO_new (&methods_ACE); 65 | 66 | if (pBIO) 67 | BIO_ctrl (pBIO, 68 | BIO_C_SET_FILE_PTR, 69 | 0, 70 | ssl_asynch_stream); 71 | 72 | return pBIO; 73 | } 74 | 75 | /** 76 | * @struct @c ACE_SSL_Asynch_Stream_Accessor 77 | * 78 | * @brief Privileged @c ACE_SSL_Asynch_Stream accessor. 79 | * 80 | * This structure is a @c friend to the @c ACE_SSL_Asynch_Stream 81 | * class so that it can gain access to the protected 82 | * ssl_bio_{read,write}() methods in that class. It is full declared 83 | * in this implementation file to hide its interface from users to 84 | * prevent potential abuse of the friend relationship between it and 85 | * the @c ACE_SSL_Asynch_Stream class. 86 | */ 87 | struct ACE_SSL_Asynch_Stream_Accessor 88 | { 89 | static int read (ACE_SSL_Asynch_Stream * stream, 90 | char * buf, 91 | size_t len, 92 | int & errval) 93 | { 94 | return stream->ssl_bio_read (buf, len, errval); 95 | } 96 | 97 | static int write (ACE_SSL_Asynch_Stream * stream, 98 | const char * buf, 99 | size_t len, 100 | int & errval) 101 | { 102 | return stream->ssl_bio_write (buf, len, errval); 103 | } 104 | }; 105 | 106 | ACE_END_VERSIONED_NAMESPACE_DECL 107 | 108 | int 109 | ACE_ASYNCH_BIO_NEW_NAME (BIO * pBIO) 110 | { 111 | pBIO->init = 0; // not initialized 112 | pBIO->num = 0; // still zero ( we can use it ) 113 | pBIO->ptr = 0; // will be pointer to ACE_SSL_Asynch_Stream 114 | pBIO->flags = 0; // 115 | 116 | return 1; 117 | } 118 | 119 | int 120 | ACE_ASYNCH_BIO_FREE_NAME (BIO * pBIO) 121 | { 122 | if (pBIO && pBIO->shutdown) 123 | { 124 | pBIO->ptr = 0; 125 | pBIO->init = 0; 126 | pBIO->num = 0; 127 | pBIO->flags = 0; 128 | 129 | return 1; 130 | } 131 | 132 | return 0; 133 | } 134 | 135 | int 136 | ACE_ASYNCH_BIO_READ_NAME (BIO * pBIO, char * buf, int len) 137 | { 138 | BIO_clear_retry_flags (pBIO); 139 | 140 | ACE_SSL_Asynch_Stream * const p_stream = 141 | static_cast (pBIO->ptr); 142 | 143 | if (pBIO->init == 0 || p_stream == 0 || buf == 0 || len <= 0) 144 | return -1; 145 | 146 | BIO_clear_retry_flags (pBIO); 147 | 148 | int errval = 0; 149 | 150 | int retval = 151 | ACE_SSL_Asynch_Stream_Accessor::read (p_stream, 152 | buf, 153 | len, 154 | errval); 155 | 156 | if (retval >= 0) 157 | return retval; 158 | 159 | if (errval == EINPROGRESS) 160 | BIO_set_retry_read (pBIO); 161 | 162 | return -1; 163 | } 164 | 165 | int 166 | ACE_ASYNCH_BIO_WRITE_NAME (BIO * pBIO, const char * buf, int len) 167 | { 168 | BIO_clear_retry_flags (pBIO); 169 | 170 | ACE_SSL_Asynch_Stream * p_stream = 171 | static_cast (pBIO->ptr); 172 | 173 | if (pBIO->init == 0 || p_stream == 0 || buf == 0 || len <= 0) 174 | return -1; 175 | 176 | BIO_clear_retry_flags (pBIO); 177 | 178 | int errval = 0; 179 | 180 | int retval = 181 | ACE_SSL_Asynch_Stream_Accessor::write (p_stream, 182 | buf, 183 | len, 184 | errval); 185 | 186 | if (retval >= 0) 187 | return retval; 188 | 189 | if (errval == EINPROGRESS) 190 | BIO_set_retry_write (pBIO); 191 | 192 | return -1; 193 | } 194 | 195 | long 196 | ACE_ASYNCH_BIO_CTRL_NAME (BIO * pBIO, int cmd, long num, void *ptr) 197 | { 198 | long ret = 1; 199 | 200 | switch (cmd) 201 | { 202 | case BIO_C_SET_FILE_PTR: 203 | pBIO->shutdown = static_cast (num); 204 | pBIO->ptr = ptr; 205 | pBIO->init = 1; 206 | break; 207 | 208 | case BIO_CTRL_INFO: 209 | ret = 0; 210 | break; 211 | 212 | case BIO_CTRL_GET_CLOSE: 213 | ret = pBIO->shutdown; 214 | break; 215 | 216 | case BIO_CTRL_SET_CLOSE: 217 | pBIO->shutdown = static_cast (num); 218 | break; 219 | 220 | case BIO_CTRL_PENDING: 221 | case BIO_CTRL_WPENDING: 222 | ret = 0; 223 | break; 224 | 225 | case BIO_CTRL_DUP: 226 | case BIO_CTRL_FLUSH: 227 | ret = 1; 228 | break; 229 | 230 | default: 231 | ret = 0; 232 | break; 233 | } 234 | 235 | return ret; 236 | } 237 | 238 | int 239 | ACE_ASYNCH_BIO_PUTS_NAME (BIO *pBIO, const char *str) 240 | { 241 | size_t const n = ACE_OS::strlen (str); 242 | 243 | return ACE_ASYNCH_BIO_WRITE_NAME (pBIO, 244 | str, 245 | ACE_Utils::truncate_cast (n)); 246 | } 247 | 248 | #endif /* OPENSSL_VERSION_NUMBER > 0x0090581fL && (ACE_WIN32 || 249 | ACE_HAS_AIO_CALLS) */ 250 | -------------------------------------------------------------------------------- /ace_ssl/SSL_Asynch_BIO.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | //============================================================================= 4 | /** 5 | * @file SSL_Asynch_BIO.h 6 | * 7 | * $Id: SSL_Asynch_BIO.h 80826 2008-03-04 14:51:23Z wotte $ 8 | * 9 | * @author Alexander Libman 10 | * @author Ossama Othman 11 | * 12 | */ 13 | //============================================================================= 14 | 15 | #ifndef ACE_SSL_ASYNCH_BIO_H 16 | #define ACE_SSL_ASYNCH_BIO_H 17 | 18 | #include /**/ "ace/pre.h" 19 | 20 | #include "SSL_Export.h" 21 | 22 | #if !defined (ACE_LACKS_PRAGMA_ONCE) 23 | #pragma once 24 | #endif /* ACE_LACKS_PRAGMA_ONCE */ 25 | 26 | // This must be included before any include on LynxOS 27 | #include "ace/os_include/os_stdio.h" 28 | 29 | #include 30 | 31 | #if OPENSSL_VERSION_NUMBER > 0x0090581fL && ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS))) 32 | 33 | ACE_BEGIN_VERSIONED_NAMESPACE_DECL 34 | extern BIO * ACE_SSL_make_BIO (void * ssl_asynch_stream); 35 | ACE_END_VERSIONED_NAMESPACE_DECL 36 | 37 | #endif /* OPENSSL_VERSION_NUMBER > 0x0090581fL (ACE_WIN32 || 38 | ACE_HAS_AIO_CALLS) */ 39 | 40 | #include /**/ "ace/post.h" 41 | 42 | #endif /* ACE_SSL_ASYNCH_BIO_H */ 43 | -------------------------------------------------------------------------------- /ace_ssl/SSL_Asynch_Stream.inl: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | // 3 | // $Id: SSL_Asynch_Stream.inl 83916 2008-11-28 16:32:21Z johnnyw $ 4 | 5 | ACE_BEGIN_VERSIONED_NAMESPACE_DECL 6 | 7 | ACE_INLINE SSL * 8 | ACE_SSL_Asynch_Stream::ssl (void) const 9 | { 10 | return this->ssl_; 11 | } 12 | 13 | ACE_END_VERSIONED_NAMESPACE_DECL 14 | -------------------------------------------------------------------------------- /ace_ssl/SSL_Context.inl: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | // 3 | // $Id: SSL_Context.inl 83916 2008-11-28 16:32:21Z johnnyw $ 4 | 5 | ACE_BEGIN_VERSIONED_NAMESPACE_DECL 6 | 7 | ACE_INLINE 8 | ACE_SSL_Data_File::ACE_SSL_Data_File (void) 9 | : type_ (-1) 10 | { 11 | } 12 | 13 | ACE_INLINE 14 | ACE_SSL_Data_File::ACE_SSL_Data_File (const char *file_name, 15 | int type) 16 | : file_name_ (file_name), 17 | type_ (type) 18 | { 19 | } 20 | 21 | ACE_INLINE const char * 22 | ACE_SSL_Data_File::file_name (void) const 23 | { 24 | return this->file_name_.c_str (); 25 | } 26 | 27 | ACE_INLINE int 28 | ACE_SSL_Data_File::type (void) const 29 | { 30 | return this->type_; 31 | } 32 | 33 | // **************************************************************** 34 | 35 | ACE_INLINE void 36 | ACE_SSL_Context::check_context (void) 37 | { 38 | if (this->context_ == 0) 39 | { 40 | this->set_mode (); 41 | } 42 | 43 | ::SSL_CTX_set_verify (this->context_, this->default_verify_mode (), 44 | this->default_verify_callback ()); 45 | } 46 | 47 | ACE_INLINE SSL_CTX * 48 | ACE_SSL_Context::context (void) 49 | { 50 | this->check_context (); 51 | return this->context_; 52 | } 53 | 54 | ACE_INLINE int 55 | ACE_SSL_Context::private_key_type (void) const 56 | { 57 | return this->private_key_.type (); 58 | } 59 | 60 | ACE_INLINE const char* 61 | ACE_SSL_Context::private_key_file_name (void) const 62 | { 63 | return this->private_key_.file_name (); 64 | } 65 | 66 | ACE_INLINE int 67 | ACE_SSL_Context::certificate_type (void) const 68 | { 69 | return this->certificate_.type (); 70 | } 71 | 72 | ACE_INLINE const char* 73 | ACE_SSL_Context::certificate_file_name (void) const 74 | { 75 | return this->certificate_.file_name (); 76 | } 77 | 78 | ACE_INLINE int 79 | ACE_SSL_Context::dh_params_file_type (void) const 80 | { 81 | return this->dh_params_.type (); 82 | } 83 | 84 | ACE_INLINE const char* 85 | ACE_SSL_Context::dh_params_file_name (void) const 86 | { 87 | return this->dh_params_.file_name (); 88 | } 89 | 90 | ACE_INLINE void 91 | ACE_SSL_Context::default_verify_mode (int mode) 92 | { 93 | this->default_verify_mode_ = mode; 94 | } 95 | 96 | ACE_INLINE int 97 | ACE_SSL_Context::default_verify_mode (void) const 98 | { 99 | return this->default_verify_mode_; 100 | } 101 | 102 | ACE_INLINE void 103 | ACE_SSL_Context::default_verify_callback (int (*callback) (int, X509_STORE_CTX*)) 104 | { 105 | this->default_verify_callback_ = callback; 106 | } 107 | 108 | ACE_INLINE int (*ACE_SSL_Context::default_verify_callback(void) const)(int,X509_STORE_CTX *) 109 | { 110 | return this->default_verify_callback_; 111 | } 112 | 113 | ACE_INLINE int 114 | ACE_SSL_Context::get_mode (void) const 115 | { 116 | return this->mode_; 117 | } 118 | 119 | ACE_INLINE int 120 | ACE_SSL_Context::have_trusted_ca (void) const 121 | { 122 | return this->have_ca_; 123 | } 124 | 125 | ACE_END_VERSIONED_NAMESPACE_DECL 126 | -------------------------------------------------------------------------------- /ace_ssl/SSL_Export.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | // $Id: SSL_Export.h 80826 2008-03-04 14:51:23Z wotte $ 3 | // Definition for Win32 Export directives. 4 | // This file is generated automatically by 5 | // generate_export_file.pl 6 | // ------------------------------ 7 | #if !defined (ACE_SSL_EXPORT_H) 8 | #define ACE_SSL_EXPORT_H 9 | 10 | #include /**/ "ace/config-all.h" 11 | 12 | //#if defined (ACE_AS_STATIC_LIBS) && !defined (ACE_SSL_HAS_DLL) 13 | //# define ACE_SSL_HAS_DLL 0 14 | //#endif /* ACE_AS_STATIC_LIBS && ACE_SSL_HAS_DLL */ 15 | // 16 | //#if !defined (ACE_SSL_HAS_DLL) 17 | //#define ACE_SSL_HAS_DLL 1 18 | //#endif /* ! ACE_SSL_HAS_DLL */ 19 | 20 | #if defined (ACE_SSL_HAS_DLL) 21 | # if (ACE_SSL_HAS_DLL == 1) 22 | # if defined (ACE_SSL_BUILD_DLL) 23 | # define ACE_SSL_Export ACE_Proper_Export_Flag 24 | # define ACE_SSL_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) 25 | # define ACE_SSL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) 26 | # else 27 | # define ACE_SSL_Export ACE_Proper_Import_Flag 28 | # define ACE_SSL_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) 29 | # define ACE_SSL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) 30 | # endif /* ACE_SSL_BUILD_DLL */ 31 | # else 32 | # define ACE_SSL_Export 33 | # define ACE_SSL_SINGLETON_DECLARATION(T) 34 | # define ACE_SSL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) 35 | # endif /* ! ACE_SSL_HAS_DLL == 1 */ 36 | #else 37 | # define ACE_SSL_Export 38 | # define ACE_SSL_SINGLETON_DECLARATION(T) 39 | # define ACE_SSL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) 40 | #endif /* ACE_SSL_HAS_DLL */ 41 | 42 | #endif /* ACE_SSL_EXPORT_H */ 43 | 44 | // End of auto generated file. 45 | -------------------------------------------------------------------------------- /ace_ssl/SSL_SOCK.cpp: -------------------------------------------------------------------------------- 1 | // $Id: SSL_SOCK.cpp 91368 2010-08-16 13:03:34Z mhengstmengel $ 2 | 3 | #include "SSL_SOCK.h" 4 | 5 | #if !defined (__ACE_INLINE__) 6 | #include "SSL_SOCK.inl" 7 | #endif /* __ACE_INLINE__ */ 8 | 9 | #include "ace/OS_NS_errno.h" 10 | #include "ace/os_include/os_signal.h" 11 | 12 | ACE_BEGIN_VERSIONED_NAMESPACE_DECL 13 | 14 | ACE_SSL_SOCK::ACE_SSL_SOCK (void) 15 | { 16 | ACE_TRACE ("ACE_SSL_SOCK::ACE_SSL_SOCK"); 17 | } 18 | 19 | ACE_SSL_SOCK::~ACE_SSL_SOCK (void) 20 | { 21 | ACE_TRACE ("ACE_SSL_SOCK::~ACE_SSL_SOCK"); 22 | } 23 | 24 | int 25 | ACE_SSL_SOCK::enable (int value) const 26 | { 27 | ACE_TRACE ("ACE_SSL_SOCK::enable"); 28 | 29 | switch (value) 30 | { 31 | #ifdef SIGURG 32 | case SIGURG: 33 | case ACE_SIGURG: 34 | #endif /* SIGURG */ 35 | case SIGIO: 36 | case ACE_SIGIO: 37 | case ACE_CLOEXEC: 38 | ACE_NOTSUP_RETURN (-1); 39 | case ACE_NONBLOCK: 40 | return ACE_IPC_SAP::enable (value); 41 | default: 42 | return -1; 43 | } 44 | } 45 | 46 | int 47 | ACE_SSL_SOCK::disable (int value) const 48 | { 49 | ACE_TRACE("ACE_SSL_SOCK::disable"); 50 | switch (value) 51 | { 52 | #ifdef SIGURG 53 | case SIGURG: 54 | case ACE_SIGURG: 55 | #endif /* SIGURG */ 56 | case SIGIO: 57 | case ACE_SIGIO: 58 | case ACE_CLOEXEC: 59 | ACE_NOTSUP_RETURN (-1); 60 | case ACE_NONBLOCK: 61 | return ACE_IPC_SAP::disable (value); 62 | default: 63 | return -1; 64 | } 65 | } 66 | 67 | ACE_END_VERSIONED_NAMESPACE_DECL 68 | -------------------------------------------------------------------------------- /ace_ssl/SSL_SOCK.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | //============================================================================= 4 | /** 5 | * @file SSL_SOCK.h 6 | * 7 | * $Id: SSL_SOCK.h 91685 2010-09-09 09:35:14Z johnnyw $ 8 | * 9 | * @author Ossama Othman 10 | */ 11 | //============================================================================= 12 | 13 | 14 | #ifndef ACE_SSL_SOCK_H 15 | #define ACE_SSL_SOCK_H 16 | 17 | #include /**/ "ace/pre.h" 18 | 19 | #include "SSL_Export.h" 20 | 21 | #if !defined (ACE_LACKS_PRAGMA_ONCE) 22 | # pragma once 23 | #endif /* ACE_LACKS_PRAGMA_ONCE */ 24 | 25 | #include "ace/SOCK.h" 26 | 27 | ACE_BEGIN_VERSIONED_NAMESPACE_DECL 28 | 29 | /** 30 | * @class ACE_SSL_SOCK 31 | * 32 | * @brief An abstract class that forms the basis for more specific 33 | * classes, such as "ACE_SSL_SOCK_Acceptor" and 34 | * "ACE_SSL_SOCK_Stream". Do not instantiate this class. 35 | * 36 | * This class provides functions that are common to all of the 37 | * ACE_SSL_SOCK_* classes. ACE_SSL_SOCK provides the ability 38 | * to get and set socket options, get the local and remote 39 | * addresses, and close the socket. 40 | */ 41 | class ACE_SSL_Export ACE_SSL_SOCK : public ACE_SOCK 42 | { 43 | public: 44 | 45 | /** 46 | * Override ACE_SOCK base class implementations with these SSL 47 | * specific ones. 48 | */ 49 | //@{ 50 | int set_option (int level, 51 | int option, 52 | void *optval, 53 | int optlen) const; 54 | int get_option (int level, 55 | int option, 56 | void *optval, 57 | int *optlen) const; 58 | int enable (int value) const; 59 | int disable (int value) const; 60 | void set_handle (ACE_HANDLE); 61 | ACE_HANDLE get_handle (void) const; 62 | int control (int cmd, void *arg) const; 63 | //@} 64 | 65 | protected: 66 | 67 | /// Default constructor is private to prevent instances of this class 68 | /// from being defined. 69 | ACE_SSL_SOCK (void); 70 | 71 | /// Destructor 72 | /** 73 | * Not a virtual destructor. Protected destructor to prevent 74 | * operator delete() from being called through a base class 75 | * ACE_SSL_SOCK pointer/reference. 76 | */ 77 | ~ACE_SSL_SOCK (void); 78 | 79 | }; 80 | 81 | ACE_END_VERSIONED_NAMESPACE_DECL 82 | 83 | #if defined (__ACE_INLINE__) 84 | #include "SSL_SOCK.inl" 85 | #endif /* __ACE_INLINE__ */ 86 | 87 | #include /**/ "ace/post.h" 88 | 89 | #endif /* ACE_SSL_SOCK_H */ 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /ace_ssl/SSL_SOCK.inl: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | // 3 | // $Id: SSL_SOCK.inl 80826 2008-03-04 14:51:23Z wotte $ 4 | 5 | #include "ace/OS_NS_sys_socket.h" 6 | 7 | ACE_BEGIN_VERSIONED_NAMESPACE_DECL 8 | 9 | ACE_INLINE void 10 | ACE_SSL_SOCK::set_handle (ACE_HANDLE fd) 11 | { 12 | this->ACE_SOCK::set_handle (fd); 13 | } 14 | 15 | ACE_INLINE ACE_HANDLE 16 | ACE_SSL_SOCK::get_handle (void) const 17 | { 18 | // return this->ssl_ ? (ACE_HANDLE) ::SSL_get_fd (this->ssl_) : ACE_INVALID_HANDLE; 19 | return this->ACE_SOCK::get_handle (); 20 | } 21 | 22 | 23 | ACE_INLINE int 24 | ACE_SSL_SOCK::control (int cmd, void *arg) const 25 | { 26 | return ACE_OS::ioctl (this->get_handle (), cmd, arg); 27 | } 28 | 29 | ACE_INLINE int 30 | ACE_SSL_SOCK::set_option (int level, 31 | int option, 32 | void *optval, 33 | int optlen) const 34 | { 35 | // switch (option) 36 | // { 37 | // case SO_SNDBUF: 38 | // return ::BIO_set_write_buffer_size (this->io_bio_, *((int *) optval)); 39 | // case SO_RCVCBUF: 40 | // return ::BIO_set_read_buffer_size (this->io_bio_, *((int *) optval)); 41 | // default: 42 | return ACE_OS::setsockopt (this->get_handle (), 43 | level, 44 | option, (char *) optval, 45 | optlen); 46 | // } 47 | } 48 | 49 | // Provides access to the ACE_OS::getsockopt system call. 50 | 51 | ACE_INLINE int 52 | ACE_SSL_SOCK::get_option (int level, 53 | int option, 54 | void *optval, 55 | int *optlen) const 56 | { 57 | // switch (option) 58 | // { 59 | // case SO_SNDBUF: 60 | // return ::BIO_get_write_buffer_size (this->io_bio_, *((int *) optval)); 61 | // case SO_RCVCBUF: 62 | // return ::BIO_get_read_buffer_size (this->io_bio_, *((int *) optval)); 63 | // default: 64 | return ACE_OS::getsockopt (this->get_handle (), 65 | level, 66 | option, (char *) optval, 67 | optlen); 68 | // } 69 | } 70 | 71 | ACE_END_VERSIONED_NAMESPACE_DECL 72 | -------------------------------------------------------------------------------- /ace_ssl/SSL_SOCK_Acceptor.cpp: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | // 3 | // $Id: SSL_SOCK_Acceptor.cpp 91368 2010-08-16 13:03:34Z mhengstmengel $ 4 | 5 | 6 | #include "SSL_SOCK_Acceptor.h" 7 | 8 | #include "ace/Handle_Set.h" 9 | #include "ace/OS_Errno.h" 10 | #include "ace/OS_NS_errno.h" 11 | #include "ace/Log_Msg.h" 12 | #include "ace/Time_Value.h" 13 | #include "ace/Countdown_Time.h" 14 | #include "ace/Truncate.h" 15 | 16 | #if !defined (__ACE_INLINE__) 17 | #include "SSL_SOCK_Acceptor.inl" 18 | #endif /* __ACE_INLINE__ */ 19 | 20 | ACE_BEGIN_VERSIONED_NAMESPACE_DECL 21 | 22 | ACE_ALLOC_HOOK_DEFINE(ACE_SSL_SOCK_Acceptor) 23 | 24 | ACE_SSL_SOCK_Acceptor::~ACE_SSL_SOCK_Acceptor (void) 25 | { 26 | ACE_TRACE ("ACE_SSL_SOCK_Acceptor::~ACE_SSL_SOCK_Acceptor"); 27 | } 28 | 29 | 30 | int ACE_SSL_SOCK_Acceptor::net_accept(ACE_SSL_SOCK_Stream &new_stream, ACE_Addr *remote_addr, 31 | ACE_Time_Value *timeout, bool restart, bool reset_new_handle) 32 | { 33 | ACE_SOCK_Stream temp_stream; 34 | 35 | if (-1 == this->acceptor_.accept(temp_stream, 36 | remote_addr, 37 | timeout, 38 | restart, 39 | reset_new_handle)) { 40 | return -1; 41 | } 42 | 43 | new_stream.set_handle(temp_stream.get_handle()); 44 | temp_stream.set_handle(ACE_INVALID_HANDLE); 45 | return 0; 46 | } 47 | 48 | int 49 | ACE_SSL_SOCK_Acceptor::ssl_accept (ACE_SSL_SOCK_Stream &new_stream, 50 | ACE_Time_Value *timeout) const 51 | { 52 | SSL *ssl = new_stream.ssl (); 53 | 54 | if (SSL_is_init_finished (ssl)) 55 | return 0; 56 | 57 | if (!SSL_in_accept_init (ssl)) 58 | ::SSL_set_accept_state (ssl); 59 | 60 | ACE_HANDLE handle = new_stream.get_handle (); 61 | 62 | // We're going to call SSL_accept, optionally doing ACE::select and 63 | // retrying the SSL_accept, until the SSL handshake is done or 64 | // it fails. 65 | // To get the timeout affect, set the socket to nonblocking mode 66 | // before beginning if there is a timeout specified. If the timeout 67 | // is 0 (wait as long as it takes) then don't worry about the blocking 68 | // status; we'll block in SSL_accept if the socket is blocking, and 69 | // block in ACE::select if not. 70 | int reset_blocking_mode = 0; 71 | if (timeout != 0) 72 | { 73 | reset_blocking_mode = ACE_BIT_DISABLED (ACE::get_flags (handle), 74 | ACE_NONBLOCK); 75 | // Set the handle into non-blocking mode if it's not already 76 | // in it. 77 | if (reset_blocking_mode 78 | && ACE::set_flags (handle, 79 | ACE_NONBLOCK) == -1) 80 | return -1; 81 | } 82 | 83 | // Take into account the time between each select() call below. 84 | ACE_Countdown_Time countdown (timeout); 85 | 86 | int status; 87 | do 88 | { 89 | // These handle sets are used to set up for whatever SSL_accept 90 | // says it wants next. They're reset on each pass around the loop. 91 | ACE_Handle_Set rd_handle; 92 | ACE_Handle_Set wr_handle; 93 | 94 | status = ::SSL_accept (ssl); 95 | switch (::SSL_get_error (ssl, status)) 96 | { 97 | case SSL_ERROR_NONE: 98 | status = 0; // To tell caller about success 99 | break; // Done 100 | 101 | case SSL_ERROR_WANT_WRITE: 102 | wr_handle.set_bit (handle); 103 | status = 1; // Wait for more activity 104 | break; 105 | 106 | case SSL_ERROR_WANT_READ: 107 | rd_handle.set_bit (handle); 108 | status = 1; // Wait for more activity 109 | break; 110 | 111 | case SSL_ERROR_ZERO_RETURN: 112 | // The peer has notified us that it is shutting down via 113 | // the SSL "close_notify" message so we need to 114 | // shutdown, too. 115 | status = -1; 116 | break; 117 | 118 | case SSL_ERROR_SYSCALL: 119 | // On some platforms (e.g. MS Windows) OpenSSL does not 120 | // store the last error in errno so explicitly do so. 121 | // 122 | // Explicitly check for EWOULDBLOCK since it doesn't get 123 | // converted to an SSL_ERROR_WANT_{READ,WRITE} on some 124 | // platforms. If SSL_accept failed outright, though, don't 125 | // bother checking more. This can happen if the socket gets 126 | // closed during the handshake. 127 | if (ACE_OS::set_errno_to_last_error () == EWOULDBLOCK && 128 | status == -1) 129 | { 130 | // Although the SSL_ERROR_WANT_READ/WRITE isn't getting 131 | // set correctly, the read/write state should be valid. 132 | // Use that to decide what to do. 133 | status = 1; // Wait for more activity 134 | if (SSL_want_write (ssl)) 135 | wr_handle.set_bit (handle); 136 | else if (SSL_want_read (ssl)) 137 | rd_handle.set_bit (handle); 138 | else 139 | status = -1; // Doesn't want anything - bail out 140 | } 141 | else 142 | status = -1; 143 | break; 144 | 145 | default: 146 | ACE_SSL_Context::report_error (); 147 | status = -1; 148 | break; 149 | } 150 | 151 | if (status == 1) 152 | { 153 | // Must have at least one handle to wait for at this point. 154 | ACE_ASSERT (rd_handle.num_set() == 1 || wr_handle.num_set () == 1); 155 | status = ACE::select (int (handle) + 1, 156 | &rd_handle, 157 | &wr_handle, 158 | 0, 159 | timeout); 160 | 161 | (void) countdown.update (); 162 | 163 | // 0 is timeout, so we're done. 164 | // -1 is error, so we're done. 165 | // Could be both handles set (same handle in both masks) so 166 | // set to 1. 167 | if (status >= 1) 168 | status = 1; 169 | else // Timeout or failure 170 | status = -1; 171 | } 172 | 173 | } while (status == 1 && !SSL_is_init_finished (ssl)); 174 | 175 | if (reset_blocking_mode) 176 | { 177 | ACE_Errno_Guard eguard (errno); 178 | ACE::clr_flags (handle, ACE_NONBLOCK); 179 | } 180 | 181 | return (status == -1 ? -1 : 0); 182 | 183 | } 184 | 185 | // General purpose routine for accepting new connections. 186 | // Since our underlying acceptor is of the plain old ACE_SOCK_Acceptor 187 | // variety, get the basic socket setup done with it, then take care of 188 | // the SSL handshake if the socket is accepted. 189 | int 190 | ACE_SSL_SOCK_Acceptor::accept (ACE_SSL_SOCK_Stream &new_stream, 191 | ACE_Addr *remote_addr, 192 | ACE_Time_Value *timeout, 193 | bool restart, 194 | bool reset_new_handle) const 195 | { 196 | ACE_TRACE ("ACE_SSL_SOCK_Acceptor::accept"); 197 | 198 | // Take into account the time to complete the basic TCP handshake 199 | // and the SSL handshake. 200 | ACE_Countdown_Time countdown (timeout); 201 | 202 | ACE_SOCK_Stream temp_stream; 203 | if (-1 == this->acceptor_.accept (temp_stream, 204 | remote_addr, 205 | timeout, 206 | restart, 207 | reset_new_handle)) 208 | return -1; 209 | 210 | (void) countdown.update (); 211 | 212 | new_stream.set_handle (temp_stream.get_handle ()); 213 | temp_stream.set_handle (ACE_INVALID_HANDLE); 214 | 215 | if (this->ssl_accept (new_stream, timeout) == -1) 216 | { 217 | new_stream.close (); 218 | new_stream.set_handle (ACE_INVALID_HANDLE); 219 | return -1; 220 | } 221 | 222 | return 0; 223 | 224 | } 225 | 226 | int 227 | ACE_SSL_SOCK_Acceptor::accept (ACE_SSL_SOCK_Stream &new_stream, 228 | ACE_Accept_QoS_Params qos_params, 229 | ACE_Addr *remote_addr, 230 | ACE_Time_Value *timeout, 231 | bool restart, 232 | bool reset_new_handle) const 233 | { 234 | ACE_TRACE ("ACE_SSL_SOCK_Acceptor::accept"); 235 | 236 | // Take into account the time to complete the basic TCP handshake 237 | // and the SSL handshake. 238 | ACE_Countdown_Time countdown (timeout); 239 | 240 | ACE_SOCK_Stream temp_stream; 241 | if (-1 == this->acceptor_.accept (temp_stream, 242 | qos_params, 243 | remote_addr, 244 | timeout, 245 | restart, 246 | reset_new_handle)) 247 | return -1; 248 | 249 | (void) countdown.update (); 250 | 251 | new_stream.set_handle (temp_stream.get_handle ()); 252 | temp_stream.set_handle (ACE_INVALID_HANDLE); 253 | 254 | if (this->ssl_accept (new_stream, timeout) == -1) 255 | { 256 | new_stream.close (); 257 | new_stream.set_handle (ACE_INVALID_HANDLE); 258 | return -1; 259 | } 260 | 261 | return 0; 262 | } 263 | 264 | ACE_END_VERSIONED_NAMESPACE_DECL 265 | -------------------------------------------------------------------------------- /ace_ssl/SSL_SOCK_Acceptor.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | //============================================================================= 4 | /** 5 | * @file SSL_SOCK_Acceptor.h 6 | * 7 | * $Id: SSL_SOCK_Acceptor.h 82723 2008-09-16 09:35:44Z johnnyw $ 8 | * 9 | * @author John Heitmann 10 | * @author Chris Zimman 11 | * @author Ossama Othman 12 | */ 13 | //============================================================================= 14 | 15 | #ifndef ACE_SSL_SOCK_ACCEPTOR_H 16 | #define ACE_SSL_SOCK_ACCEPTOR_H 17 | 18 | #include /**/ "ace/pre.h" 19 | 20 | #include "SSL_Export.h" 21 | 22 | #if !defined (ACE_LACKS_PRAGMA_ONCE) 23 | # pragma once 24 | #endif /* ACE_LACKS_PRAGMA_ONCE */ 25 | 26 | #include "SSL_SOCK_Stream.h" 27 | 28 | #include "ace/SOCK_Acceptor.h" 29 | #include "ace/OS_QoS.h" 30 | 31 | ACE_BEGIN_VERSIONED_NAMESPACE_DECL 32 | 33 | /** 34 | * @class ACE_SSL_SOCK_Acceptor 35 | * 36 | * @brief Defines a factory that creates new @c ACE_SSL_SOCK_Stream 37 | * objects passively. 38 | * 39 | * The ACE_SSL_SOCK_Acceptor has its own @c ACE_SOCK_Acceptor 40 | * which handles the basic socket acceptance. This class is a 41 | * wrapper which adds the SSL acceptance handshake handling. 42 | * Since SSL is record oriented, some additional steps must be taken 43 | * after the basic socket acceptance to complete the SSL handshake that 44 | * takes place at session establishment. 45 | * 46 | * @note The user must currently ensure that only one thread services 47 | * a given SSL session at any given time since some underlying 48 | * SSL implementations, such as OpenSSL, are not entirely 49 | * thread-safe or reentrant. 50 | */ 51 | class ACE_SSL_Export ACE_SSL_SOCK_Acceptor : public ACE_SSL_SOCK 52 | { 53 | public: 54 | 55 | /// Default constructor. 56 | ACE_SSL_SOCK_Acceptor (void); 57 | 58 | /// Default destructor. 59 | ~ACE_SSL_SOCK_Acceptor (void); 60 | 61 | /** 62 | * Initiate a passive mode SSL/BSD-style acceptor socket. 63 | * @param local_sap The address that we're going to listen for 64 | * connections on. If this is @c ACE_Addr::sap_any, 65 | * this socket listens on an the "any" IP address 66 | * and selects an unused port. To find out what port 67 | * was selected, call this object's 68 | * @c ACE_SOCK::get_local_addr(ACE_Addr&) method 69 | * upon return. 70 | */ 71 | ACE_SSL_SOCK_Acceptor (const ACE_Addr &local_sap, 72 | int reuse_addr = 0, 73 | int protocol_family = PF_UNSPEC, 74 | int backlog = ACE_DEFAULT_BACKLOG, 75 | int protocol = 0); 76 | 77 | /** 78 | * Initiate a passive-mode QoS-enabled acceptor socket. 79 | * @param local_sap The address that we're going to listen for 80 | * connections on. If this is @c ACE_Addr::sap_any, 81 | * this socket listens on an the "any" IP address 82 | * and selects an unused port. To find out what port 83 | * was selected, call this object's 84 | * @c ACE_SOCK::get_local_addr(ACE_Addr&) method 85 | * upon return. 86 | */ 87 | ACE_SSL_SOCK_Acceptor (const ACE_Addr &local_sap, 88 | ACE_Protocol_Info *protocolinfo, 89 | ACE_SOCK_GROUP g, 90 | u_long flags, 91 | int reuse_addr, 92 | int protocol_family = PF_UNSPEC, 93 | int backlog = ACE_DEFAULT_BACKLOG, 94 | int protocol = 0); 95 | 96 | /** 97 | * Initiate a passive mode SSL/BSD-style acceptor socket. 98 | * @param local_sap The address that we're going to listen for 99 | * connections on. If this is @c ACE_Addr::sap_any, 100 | * this socket listens on an the "any" IP address 101 | * and selects an unused port. To find out what port 102 | * was selected, call this object's 103 | * @c ACE_SOCK::get_local_addr(ACE_Addr&) method 104 | * upon return. 105 | * 106 | * @return 0 if success; -1 for failure (errno contains error code). 107 | */ 108 | int open (const ACE_Addr &local_sap, 109 | int reuse_addr = 0, 110 | int protocol_family = PF_UNSPEC, 111 | int backlog = ACE_DEFAULT_BACKLOG, 112 | int protocol = 0); 113 | 114 | /// Close the listening socket. 115 | int close (void); 116 | 117 | int net_accept(ACE_SSL_SOCK_Stream &new_stream, 118 | ACE_Addr *remote_addr = 0, 119 | ACE_Time_Value *timeout = 0, 120 | bool restart = true, 121 | bool reset_new_handle = false); 122 | 123 | /// Complete SSL passive connection establishment. 124 | int ssl_accept(ACE_SSL_SOCK_Stream &new_stream, 125 | ACE_Time_Value *timeout) const; 126 | 127 | /** 128 | * @name Passive Connection "accept" Methods 129 | * 130 | * These are the canonical methods exposed by the Acceptor pattern. 131 | */ 132 | //@{ 133 | /** 134 | * Accept a new ACE_SSL_SOCK_Stream connection. On successful return, 135 | * the socket has been accepted and the SSL handshake has been completed. 136 | * @param new_stream The @c ACE_SSL_SOCK_Stream object that will receive 137 | * the new SSL socket. 138 | * @param remote_addr Pointer to an @c ACE_INET_Addr object that will 139 | * receive the address of the peer that connected. 140 | * @param timeout The maximum time to wait for the combined socket 141 | * acceptance and handshake completion. 0 means 142 | * block forever, a timeout of {0, 0} means poll. 143 | * @param restart 1 means "restart if interrupted," that is, 144 | * if errno == EINTR. 145 | * 146 | * @return 0 if success; -1 for failure (errno contains error code). 147 | */ 148 | int accept (ACE_SSL_SOCK_Stream &new_stream, 149 | ACE_Addr *remote_addr = 0, 150 | ACE_Time_Value *timeout = 0, 151 | bool restart = true, 152 | bool reset_new_handle = false) const; 153 | 154 | /** 155 | * Accept a new ACE_SSL_SOCK_Stream connection using the RVSP QoS 156 | * information in qos_params. 157 | * @param new_stream The @c ACE_SSL_SOCK_Stream object that will receive 158 | * the new SSL socket. 159 | * @param remote_addr Pointer to an @c ACE_INET_Addr object that will 160 | * receive the address of the peer that connected. 161 | * @param timeout The maximum time to wait for the combined socket 162 | * acceptance and handshake completion. 0 means 163 | * block forever, a timeout of {0, 0} means poll. 164 | * @param restart 1 means "restart if interrupted," that is, 165 | * if errno == EINTR. 166 | * 167 | * @return 0 if success; -1 for failure (errno contains error code). 168 | */ 169 | int accept (ACE_SSL_SOCK_Stream &new_stream, 170 | ACE_Accept_QoS_Params qos_params, 171 | ACE_Addr *remote_addr = 0, 172 | ACE_Time_Value *timeout = 0, 173 | bool restart = true, 174 | bool reset_new_handle = false) const; 175 | //@} 176 | 177 | /// Meta-type info 178 | //@{ 179 | typedef ACE_INET_Addr PEER_ADDR; 180 | typedef ACE_SSL_SOCK_Stream PEER_STREAM; 181 | //@} 182 | 183 | /// Declare the dynamic allocation hooks. 184 | ACE_ALLOC_HOOK_DECLARE; 185 | 186 | private: 187 | 188 | /// The BSD-socket workhorse 189 | ACE_SOCK_Acceptor acceptor_; 190 | 191 | }; 192 | 193 | ACE_END_VERSIONED_NAMESPACE_DECL 194 | 195 | #if defined (__ACE_INLINE__) 196 | #include "SSL_SOCK_Acceptor.inl" 197 | #endif /* __ACE_INLINE__ */ 198 | 199 | #include /**/ "ace/post.h" 200 | 201 | #endif /* ACE_SSL_SOCK_ACCEPTOR_H */ 202 | -------------------------------------------------------------------------------- /ace_ssl/SSL_SOCK_Acceptor.inl: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | // 3 | // $Id: SSL_SOCK_Acceptor.inl 84619 2009-02-26 12:26:16Z johnnyw $ 4 | 5 | ACE_BEGIN_VERSIONED_NAMESPACE_DECL 6 | 7 | ACE_INLINE 8 | ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor (void) 9 | : acceptor_ () 10 | { 11 | ACE_TRACE ("ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor"); 12 | } 13 | 14 | ACE_INLINE 15 | ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor (const ACE_Addr &local_sap, 16 | int reuse_addr, 17 | int protocol_family, 18 | int backlog, 19 | int protocol) 20 | : acceptor_ (local_sap, 21 | reuse_addr, 22 | protocol_family, 23 | backlog, 24 | protocol) 25 | { 26 | ACE_TRACE ("ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor"); 27 | 28 | this->set_handle (this->acceptor_.get_handle ()); 29 | } 30 | 31 | ACE_INLINE 32 | ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor (const ACE_Addr &local_sap, 33 | ACE_Protocol_Info *protocolinfo, 34 | ACE_SOCK_GROUP g, 35 | u_long flags, 36 | int reuse_addr, 37 | int protocol_family, 38 | int backlog, 39 | int protocol) 40 | : acceptor_ (local_sap, 41 | protocolinfo, 42 | g, 43 | flags, 44 | reuse_addr, 45 | protocol_family, 46 | backlog, 47 | protocol) 48 | { 49 | ACE_TRACE ("ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor"); 50 | 51 | this->set_handle (this->acceptor_.get_handle ()); 52 | } 53 | 54 | ACE_INLINE int 55 | ACE_SSL_SOCK_Acceptor::open (const ACE_Addr &local_sap, 56 | int reuse_addr, 57 | int protocol_family, 58 | int backlog, 59 | int protocol) 60 | { 61 | ACE_TRACE ("ACE_SSL_SOCK_Acceptor::open"); 62 | if (this->acceptor_.open (local_sap, 63 | reuse_addr, 64 | protocol_family, 65 | backlog, 66 | protocol) != 0) 67 | return -1; 68 | else 69 | this->set_handle (this->acceptor_.get_handle ()); 70 | 71 | return 0; 72 | } 73 | 74 | ACE_INLINE int 75 | ACE_SSL_SOCK_Acceptor::close (void) 76 | { 77 | ACE_TRACE ("ACE_SSL_SOCK_Acceptor::close ()"); 78 | 79 | int const result = this->acceptor_.close (); 80 | this->set_handle (ACE_INVALID_HANDLE); 81 | 82 | return result; 83 | } 84 | 85 | ACE_END_VERSIONED_NAMESPACE_DECL 86 | -------------------------------------------------------------------------------- /ace_ssl/SSL_SOCK_Connector.inl: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | // 3 | // $Id: SSL_SOCK_Connector.inl 82728 2008-09-16 10:22:28Z johnnyw $ 4 | 5 | ACE_BEGIN_VERSIONED_NAMESPACE_DECL 6 | 7 | ACE_INLINE 8 | ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector (void) 9 | : connector_ () 10 | { 11 | ACE_TRACE ("ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector"); 12 | } 13 | 14 | ACE_INLINE bool 15 | ACE_SSL_SOCK_Connector::reset_new_handle (ACE_HANDLE handle) 16 | { 17 | ACE_TRACE ("ACE_SSL_SOCK_Connector::reset_new_handle"); 18 | return this->connector_.reset_new_handle (handle); 19 | } 20 | 21 | ACE_INLINE void 22 | ACE_SSL_SOCK_Connector::dump (void) const 23 | { 24 | ACE_TRACE ("ACE_SSL_SOCK_Connector::dump"); 25 | this->connector_.dump (); 26 | } 27 | 28 | ACE_END_VERSIONED_NAMESPACE_DECL 29 | -------------------------------------------------------------------------------- /ace_ssl/SSL_SOCK_Stream.inl: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | // 3 | // $Id: SSL_SOCK_Stream.inl 91103 2010-07-15 12:36:57Z mcorino $ 4 | 5 | #include "ace/OS_NS_errno.h" 6 | #include "ace/Truncate.h" 7 | 8 | ACE_BEGIN_VERSIONED_NAMESPACE_DECL 9 | 10 | ACE_INLINE void 11 | ACE_SSL_SOCK_Stream::set_handle (ACE_HANDLE fd) 12 | { 13 | if (this->ssl_ == 0 || fd == ACE_INVALID_HANDLE) 14 | { 15 | this->ACE_SSL_SOCK::set_handle (ACE_INVALID_HANDLE); 16 | return; 17 | } 18 | else 19 | { 20 | (void) ::SSL_set_fd (this->ssl_, (int) fd); 21 | this->ACE_SSL_SOCK::set_handle (fd); 22 | this->stream_.set_handle (fd); 23 | } 24 | } 25 | 26 | ACE_INLINE ssize_t 27 | ACE_SSL_SOCK_Stream::send_i (const void *buf, 28 | size_t n, 29 | int flags) const 30 | { 31 | ACE_TRACE ("ACE_SSL_SOCK_Stream::send_i"); 32 | 33 | // NOTE: Caller must provide thread-synchronization. 34 | 35 | // No send flags are supported in SSL. 36 | if (flags != 0) 37 | { 38 | ACE_NOTSUP_RETURN (-1); 39 | } 40 | 41 | int const bytes_sent = ::SSL_write (this->ssl_, 42 | static_cast (buf), 43 | ACE_Utils::truncate_cast (n)); 44 | 45 | switch (::SSL_get_error (this->ssl_, bytes_sent)) 46 | { 47 | case SSL_ERROR_NONE: 48 | return bytes_sent; 49 | 50 | case SSL_ERROR_WANT_READ: 51 | case SSL_ERROR_WANT_WRITE: 52 | errno = EWOULDBLOCK; 53 | 54 | return -1; 55 | 56 | case SSL_ERROR_ZERO_RETURN: 57 | // The peer has notified us that it is shutting down via the SSL 58 | // "close_notify" message so we need to shutdown, too. 59 | (void) ::SSL_shutdown (this->ssl_); 60 | 61 | return bytes_sent; 62 | 63 | case SSL_ERROR_SYSCALL: 64 | if (bytes_sent == 0) 65 | // An EOF occured but the SSL "close_notify" message was not 66 | // sent. This is a protocol error, but we ignore it. 67 | return 0; 68 | 69 | // If not an EOF, then fall through to "default" case. 70 | 71 | // On some platforms (e.g. MS Windows) OpenSSL does not store 72 | // the last error in errno so explicitly do so. 73 | ACE_OS::set_errno_to_last_error (); 74 | 75 | break; 76 | 77 | default: 78 | // Reset errno to prevent previous values (e.g. EWOULDBLOCK) 79 | // from being associated with fatal SSL errors. 80 | errno = 0; 81 | 82 | ACE_SSL_Context::report_error (); 83 | 84 | break; 85 | } 86 | 87 | return -1; 88 | } 89 | 90 | ACE_INLINE ssize_t 91 | ACE_SSL_SOCK_Stream::send (const void *buf, 92 | size_t n, 93 | int flags) const 94 | { 95 | return this->send_i (buf, n, flags); 96 | } 97 | 98 | ACE_INLINE ssize_t 99 | ACE_SSL_SOCK_Stream::recv_i (void *buf, 100 | size_t n, 101 | int flags, 102 | const ACE_Time_Value *timeout) const 103 | { 104 | ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_i"); 105 | 106 | // NOTE: Caller must provide thread-synchronization. 107 | 108 | int bytes_read = 0; 109 | ACE_HANDLE const handle = this->get_handle (); 110 | 111 | // Value for current I/O mode (blocking/non-blocking) 112 | int val = 0; 113 | 114 | if (timeout != 0) 115 | ACE::record_and_set_non_blocking_mode (handle, 116 | val); 117 | 118 | // Only block on select() with a timeout if no data in the 119 | // internal OpenSSL buffer is pending read completion for 120 | // the same reasons stated above, i.e. all data must be read 121 | // before blocking on select(). 122 | if (timeout != 0 123 | && !::SSL_pending (this->ssl_)) 124 | { 125 | if (ACE::enter_recv_timedwait (handle, 126 | timeout, 127 | val) == -1) 128 | return -1; 129 | } 130 | 131 | if (flags) 132 | { 133 | if (ACE_BIT_ENABLED (flags, MSG_PEEK)) 134 | { 135 | bytes_read = ::SSL_peek (this->ssl_, 136 | static_cast (buf), 137 | ACE_Utils::truncate_cast (n)); 138 | } 139 | else 140 | { 141 | ACE_NOTSUP_RETURN (-1); 142 | } 143 | } 144 | else 145 | { 146 | bytes_read = ::SSL_read (this->ssl_, 147 | static_cast (buf), 148 | ACE_Utils::truncate_cast (n)); 149 | } 150 | 151 | int const status = ::SSL_get_error (this->ssl_, bytes_read); 152 | switch (status) 153 | { 154 | case SSL_ERROR_NONE: 155 | if (timeout != 0) 156 | ACE::restore_non_blocking_mode (handle, val); 157 | 158 | return bytes_read; 159 | 160 | case SSL_ERROR_WANT_READ: 161 | case SSL_ERROR_WANT_WRITE: 162 | errno = EWOULDBLOCK; 163 | 164 | return -1; 165 | 166 | case SSL_ERROR_ZERO_RETURN: 167 | if (timeout != 0) 168 | ACE::restore_non_blocking_mode (handle, val); 169 | 170 | // The peer has notified us that it is shutting down via the SSL 171 | // "close_notify" message so we need to shutdown, too. 172 | (void) ::SSL_shutdown (this->ssl_); 173 | 174 | return bytes_read; 175 | 176 | case SSL_ERROR_SYSCALL: 177 | if (bytes_read == 0) 178 | // An EOF occured but the SSL "close_notify" message was not 179 | // sent. This is a protocol error, but we ignore it. 180 | return 0; 181 | 182 | // If not an EOF, then fall through to "default" case. 183 | 184 | // On some platforms (e.g. MS Windows) OpenSSL does not store 185 | // the last error in errno so explicitly do so. 186 | ACE_OS::set_errno_to_last_error (); 187 | 188 | break; 189 | 190 | default: 191 | // Reset errno to prevent previous values (e.g. EWOULDBLOCK) 192 | // from being associated with a fatal SSL error. 193 | errno = 0; 194 | 195 | ACE_SSL_Context::report_error (); 196 | 197 | break; 198 | } 199 | 200 | return -1; 201 | } 202 | 203 | ACE_INLINE ssize_t 204 | ACE_SSL_SOCK_Stream::recv (void *buf, 205 | size_t n, 206 | int flags) const 207 | { 208 | return this->recv_i (buf, n, flags, 0); 209 | } 210 | 211 | ACE_INLINE ssize_t 212 | ACE_SSL_SOCK_Stream::send (const void *buf, 213 | size_t n) const 214 | { 215 | ACE_TRACE ("ACE_SSL_SOCK_Stream::send"); 216 | 217 | return this->send_i (buf, n, 0); 218 | } 219 | 220 | ACE_INLINE ssize_t 221 | ACE_SSL_SOCK_Stream::recv (void *buf, 222 | size_t n) const 223 | { 224 | ACE_TRACE ("ACE_SSL_SOCK_Stream::recv"); 225 | 226 | return this->recv_i (buf, n, 0, 0); 227 | } 228 | 229 | ACE_INLINE ssize_t 230 | ACE_SSL_SOCK_Stream::send (const void *buf, 231 | size_t len, 232 | const ACE_Time_Value *timeout) const 233 | { 234 | ACE_TRACE ("ACE_SSL_SOCK_Stream::send"); 235 | return this->send (buf, len, 0, timeout); 236 | } 237 | 238 | ACE_INLINE ssize_t 239 | ACE_SSL_SOCK_Stream::recv (void *buf, 240 | size_t n, 241 | const ACE_Time_Value *timeout) const 242 | { 243 | ACE_TRACE ("ACE_SSL_SOCK_Stream::recv"); 244 | return this->recv (buf, n, 0, timeout); 245 | } 246 | 247 | ACE_INLINE ssize_t 248 | ACE_SSL_SOCK_Stream::recv_n (void *buf, int buf_size) const 249 | { 250 | ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n"); 251 | return this->recv_n (buf, buf_size, 0); 252 | } 253 | 254 | ACE_INLINE ssize_t 255 | ACE_SSL_SOCK_Stream::recv_n (void *buf, 256 | size_t len, 257 | const ACE_Time_Value *timeout, 258 | size_t *bytes_transferred) const 259 | { 260 | ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n"); 261 | return this->recv_n (buf, len, 0, timeout, bytes_transferred); 262 | } 263 | 264 | ACE_INLINE ssize_t 265 | ACE_SSL_SOCK_Stream::send_n (const void *buf, int len) const 266 | { 267 | ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n"); 268 | return this->send_n (buf, len, 0); 269 | } 270 | 271 | ACE_INLINE ssize_t 272 | ACE_SSL_SOCK_Stream::send_n (const void *buf, 273 | size_t len, 274 | const ACE_Time_Value *timeout, 275 | size_t *bytes_transferred) const 276 | { 277 | ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n"); 278 | return this->send_n (buf, len, 0, timeout, bytes_transferred); 279 | } 280 | 281 | ACE_INLINE int 282 | ACE_SSL_SOCK_Stream::close_reader (void) 283 | { 284 | ACE_TRACE ("ACE_SSL_SOCK_Stream::close_reader"); 285 | return this->stream_.close_reader (); 286 | } 287 | 288 | ACE_INLINE int 289 | ACE_SSL_SOCK_Stream::close_writer (void) 290 | { 291 | ACE_TRACE ("ACE_SSL_SOCK_Stream::close_writer"); 292 | return this->stream_.close_writer (); 293 | } 294 | 295 | ACE_INLINE int 296 | ACE_SSL_SOCK_Stream::close (void) 297 | { 298 | ACE_TRACE ("ACE_SSL_SOCK_Stream::close"); 299 | 300 | if (this->ssl_ == 0 || this->get_handle () == ACE_INVALID_HANDLE) 301 | return 0; // SSL_SOCK_Stream was never opened. 302 | 303 | // SSL_shutdown() returns 1 on successful shutdown of the SSL 304 | // connection, not 0. 305 | int const status = ::SSL_shutdown (this->ssl_); 306 | 307 | switch (::SSL_get_error (this->ssl_, status)) 308 | { 309 | case SSL_ERROR_NONE: 310 | case SSL_ERROR_SYSCALL: // Ignore this error condition. 311 | 312 | // Reset the SSL object to allow another connection to be made 313 | // using this ACE_SSL_SOCK_Stream instance. This prevents the 314 | // previous SSL session state from being associated with the new 315 | // SSL session/connection. 316 | (void) ::SSL_clear (this->ssl_); 317 | this->set_handle (ACE_INVALID_HANDLE); 318 | return this->stream_.close (); 319 | 320 | case SSL_ERROR_WANT_READ: 321 | case SSL_ERROR_WANT_WRITE: 322 | errno = EWOULDBLOCK; 323 | break; 324 | 325 | default: 326 | ACE_SSL_Context::report_error (); 327 | 328 | ACE_Errno_Guard error (errno); // Save/restore errno 329 | (void) this->stream_.close (); 330 | 331 | return -1; 332 | } 333 | 334 | return -1; 335 | } 336 | 337 | ACE_INLINE ACE_SOCK_Stream & 338 | ACE_SSL_SOCK_Stream::peer (void) 339 | { 340 | ACE_TRACE ("ACE_SSL_SOCK_Stream::peer"); 341 | return this->stream_; 342 | } 343 | 344 | ACE_INLINE SSL * 345 | ACE_SSL_SOCK_Stream::ssl (void) const 346 | { 347 | return this->ssl_; 348 | } 349 | 350 | ACE_END_VERSIONED_NAMESPACE_DECL 351 | -------------------------------------------------------------------------------- /ace_ssl/sslconf.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | //============================================================================= 4 | /** 5 | * @file sslconf.h 6 | * 7 | * $Id: sslconf.h 83879 2008-11-26 10:46:30Z smcqueen $ 8 | * 9 | * @author Carlos O'Ryan 10 | */ 11 | //============================================================================= 12 | 13 | 14 | #ifndef ACE_SSLCONF_H 15 | #define ACE_SSLCONF_H 16 | 17 | #include /**/ "ace/pre.h" 18 | 19 | #include /**/ "ace/config-all.h" 20 | 21 | #if !defined (ACE_DEFAULT_SSL_CERT_FILE) 22 | // Define a default CA certificate filename here if required e.g.: 23 | // # ifdef WIN32 24 | // # define ACE_DEFAULT_SSL_CERT_FILE "cert.pem" 25 | // # else 26 | // # define ACE_DEFAULT_SSL_CERT_FILE "/etc/ssl/cert.pem" 27 | // # endif /* WIN32 */ 28 | #endif /* ACE_DEFAULT_SSL_CERT_FILE */ 29 | 30 | #if !defined (ACE_DEFAULT_SSL_CERT_DIR) 31 | // Define a default CA certificate files directory here if required. e.g.: 32 | // # ifdef WIN32 33 | // # define ACE_DEFAULT_SSL_CERT_DIR "certs" 34 | // # else 35 | // # define ACE_DEFAULT_SSL_CERT_DIR "/etc/ssl/certs" 36 | // # endif /* WIN32 */ 37 | #endif /* ACE_DEFAULT_SSL_CERT_DIR */ 38 | 39 | #if !defined (ACE_SSL_CERT_FILE_ENV) 40 | #define ACE_SSL_CERT_FILE_ENV "SSL_CERT_FILE" 41 | #endif /* ACE_SSL_CERT_FILE_ENV */ 42 | 43 | #if !defined (ACE_SSL_CERT_DIR_ENV) 44 | #define ACE_SSL_CERT_DIR_ENV "SSL_CERT_DIR" 45 | #endif /* ACE_SSL_CERT_DIR_ENV */ 46 | 47 | #if !defined (ACE_SSL_EGD_FILE_ENV) 48 | #define ACE_SSL_EGD_FILE_ENV "SSL_EGD_FILE" 49 | #endif /* ACE_SSL_EGD_FILE_ENV */ 50 | 51 | #if !defined (ACE_SSL_RAND_FILE_ENV) 52 | #define ACE_SSL_RAND_FILE_ENV "SSL_RAND_FILE" 53 | #endif /* ACE_SSL_RAND_FILE_ENV */ 54 | 55 | #include /**/ "ace/post.h" 56 | 57 | #endif /* ACE_SSLCONF_H */ 58 | -------------------------------------------------------------------------------- /doc/RDP交互过程.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## X224传输层协议握手 5 | 6 | 客户端发送自己支持的传输层协议类型:RDP、SSL、NLA。服务端收到后根据自己支持的协议 7 | 类型计算出一个最终采用的协议发送给客户端。 8 | 9 | - 如果协议类型是RDP,什么也不做,继续MCS层握手 10 | - 如果协议类型是SSL,则进行TLS握手,并用TLS传输接下来的数据包。 11 | - 如果协议类型是NLA,先启动SSL协议过程,然后启动CredSSP身份验证过程,验证用户名 12 | 和密码是否合法,librdpp支持NTLMv2的认证协议。 13 | 14 | ### MCS层多通道握手 15 | 16 | 这里的握手完成两件事情: 17 | 18 | 1. 逐一确定启动的通道数量 19 | 2. 确定Sec层使用的加密方式 20 | 21 | ### Sec加解密层握手 22 | 23 | #### sendClientRandom 24 | 25 | 发送客户端的32位随机数 26 | 27 | 28 | RC4密钥计算过程: 29 | 30 | fn(客户端随机数,服务端随机数) = (key1, key2) 31 | 32 | 33 | 客户端:使用key1加密待发送的数据, key2解密收到的数据 34 | 服务端:使用key2加密待发送的数据, key1解密收到的数据 35 | 36 | 37 | 密钥更新: 38 | 39 | 每隔4096个数据包,根据当前密钥,计算出一个新的密钥,并采用新的密钥加解密数据, 40 | 41 | 42 | 43 | ### PDU数据层,Capability握手 44 | 45 | 46 | 47 | ## FastPath数据 48 | 49 | FastPath类型的数据经过tkpt层 -> sec层 -> pdu层路径传递数据,目前只用来传输 50 | 以下两类数据: 51 | 52 | 1.服务端的图像更新数据。 53 | 2. 客户端的输入数据。 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /doc/The NTLM Authentication Protocol and Security Support Provider.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/doc/The NTLM Authentication Protocol and Security Support Provider.html -------------------------------------------------------------------------------- /doc/The NTLM Authentication Protocol and Security Support Provider_files/sflogo.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/doc/The NTLM Authentication Protocol and Security Support Provider_files/sflogo.php -------------------------------------------------------------------------------- /doc/[MS-CSSP]-13.0-20160714.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/doc/[MS-CSSP]-13.0-20160714.pdf -------------------------------------------------------------------------------- /doc/[MS-NLMP]-28.0-20160714.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/doc/[MS-NLMP]-28.0-20160714.pdf -------------------------------------------------------------------------------- /doc/[MS-RDPBCGR]-44.0-20170316.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/doc/[MS-RDPBCGR]-44.0-20170316.pdf -------------------------------------------------------------------------------- /doc/librdpp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/doc/librdpp.png -------------------------------------------------------------------------------- /doc/librdpp.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/doc/librdpp.xmind -------------------------------------------------------------------------------- /doc/rdpmitm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/doc/rdpmitm.png -------------------------------------------------------------------------------- /doc/rdpmitm.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/doc/rdpmitm.xmind -------------------------------------------------------------------------------- /librdpp/core/bitmap.h: -------------------------------------------------------------------------------- 1 | #ifndef _RDPP_CORE_BITMAP_H_ 2 | #define _RDPP_CORE_BITMAP_H_ 3 | 4 | #include 5 | 6 | namespace rdpp { 7 | 8 | class Bitmap 9 | { 10 | public: 11 | static bool decompress(uint8_t *output, int width, int height, 12 | uint8_t *input, int size, int Bpp); 13 | 14 | static string decompress(int width, int height, 15 | const string &input, int Bpp); 16 | 17 | static int bitsPerPixel2Bpp(int bitsPerPixel); 18 | }; 19 | 20 | } // namespace rdpp 21 | 22 | #endif // _RDPP_CORE_BITMAP_H_ 23 | -------------------------------------------------------------------------------- /librdpp/core/buffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef WIN32 4 | #pragma warning(disable:4996) 5 | #include 6 | #else 7 | #include 8 | #endif 9 | 10 | #define TAG "STREAM" 11 | 12 | using namespace rdpp; 13 | 14 | void Buffer::appendUInt32Be(uint32_t x) 15 | { 16 | uint32_t be32 = htonl(x); 17 | append(&be32, sizeof(be32)); 18 | } 19 | 20 | void Buffer::appendUInt16Be(uint16_t x) 21 | { 22 | uint16_t be16 = htons(x); 23 | append(&be16, sizeof(be16)); 24 | } 25 | 26 | uint32_t Buffer::readUInt32Be() 27 | { 28 | uint32_t result = peekInt32Be(); 29 | retrieveUInt32(); 30 | return result; 31 | } 32 | 33 | uint16_t Buffer::readUInt16Be() 34 | { 35 | uint16_t result = peekInt16Be(); 36 | retrieveUInt16(); 37 | return result; 38 | } 39 | 40 | uint32_t Buffer::peekInt32Be() const 41 | { 42 | assert(length() >= sizeof(uint32_t)); 43 | uint32_t be32 = 0; 44 | ::memcpy(&be32, data(), sizeof(be32)); 45 | return ntohl(be32); 46 | } 47 | 48 | uint16_t Buffer::peekInt16Be() const 49 | { 50 | assert(length() >= sizeof(uint16_t)); 51 | uint16_t be16 = 0; 52 | ::memcpy(&be16, data(), sizeof(be16)); 53 | return ntohs(be16); 54 | } 55 | 56 | void Buffer::prependUInt32Be(uint32_t x) 57 | { 58 | uint32_t be32 = htonl(x); 59 | prepend(&be32, sizeof(be32)); 60 | } 61 | 62 | void Buffer::prependUInt16Be(uint16_t x) 63 | { 64 | uint16_t be16 = htons(x); 65 | prepend(&be16, sizeof(be16)); 66 | } 67 | -------------------------------------------------------------------------------- /librdpp/core/buffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer 3 | * 4 | * +-------------------+------------------+------------------+ 5 | * | prependable bytes | readable bytes | writable bytes | 6 | * | | (CONTENT) | | 7 | * +-------------------+------------------+------------------+ 8 | * | | | | 9 | * beginPtr <= readerPtr <= writerPtr <= endPtr 10 | */ 11 | 12 | #ifndef _RDPP_CORE_BUFFER_H_ 13 | #define _RDPP_CORE_BUFFER_H_ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace rdpp { 21 | 22 | class Buffer 23 | { 24 | public: 25 | static const size_t kCheapPrepend = 48; 26 | static const size_t kInitialSize = 1024; 27 | 28 | explicit Buffer(size_t initialSize = kInitialSize) 29 | : _buffer(kCheapPrepend + initialSize) 30 | , _readerIndex(kCheapPrepend) 31 | , _writerIndex(kCheapPrepend) 32 | {} 33 | 34 | void swap(Buffer &rhs) 35 | { 36 | _buffer.swap(rhs._buffer); 37 | std::swap(_readerIndex, rhs._readerIndex); 38 | std::swap(_writerIndex, rhs._writerIndex); 39 | } 40 | 41 | size_t length() const 42 | { return _writerIndex - _readerIndex; } 43 | 44 | size_t writableBytes() const 45 | { return _buffer.size() - _writerIndex; } 46 | 47 | size_t prependableBytes() const 48 | { return _readerIndex; } 49 | 50 | uint8_t *data() 51 | { return begin() + _readerIndex; } 52 | 53 | const uint8_t *data() const 54 | { return begin() + _readerIndex; } 55 | 56 | char *c_str() 57 | { return reinterpret_cast(data()); } 58 | 59 | void retrieve(size_t len) 60 | { 61 | assert(len <= length()); 62 | 63 | if (len < length()) 64 | _readerIndex += len; 65 | else 66 | clear(); 67 | } 68 | 69 | void retrieveUntil(const uint8_t* end) 70 | { 71 | assert(data() <= end); 72 | assert(end <= beginWrite()); 73 | retrieve(end - data()); 74 | } 75 | 76 | void retrieveUInt64() 77 | { retrieve(sizeof(uint64_t)); } 78 | 79 | void retrieveUInt32() 80 | { retrieve(sizeof(uint32_t)); } 81 | 82 | void retrieveUInt16() 83 | { retrieve(sizeof(uint16_t)); } 84 | 85 | void retrieveUInt8() 86 | { retrieve(sizeof(uint8_t)); } 87 | 88 | void clear() 89 | { 90 | _readerIndex = kCheapPrepend; 91 | _writerIndex = kCheapPrepend; 92 | } 93 | 94 | string retrieveAllAsString() 95 | { 96 | return retrieveAsString(length()); 97 | } 98 | 99 | string retrieveAsString(size_t len) 100 | { 101 | assert(len <= length()); 102 | string result((const char *)data(), len); 103 | retrieve(len); 104 | return result; 105 | } 106 | void retrieve(void *to, size_t len) 107 | { 108 | memcpy(to, data(), len); 109 | retrieve(len); 110 | } 111 | void retrieve(Buffer &s, size_t len) 112 | { 113 | s.assign(data(), len); 114 | retrieve(len); 115 | } 116 | 117 | void append(size_t len, char c) 118 | { 119 | ensureWritableBytes(len); 120 | memset(beginWrite(), c, len); 121 | hasWritten(len); 122 | } 123 | 124 | void append(const uint8_t *data, size_t len) 125 | { 126 | ensureWritableBytes(len); 127 | std::copy(data, data + len, beginWrite()); 128 | hasWritten(len); 129 | } 130 | 131 | void append(const void *data, size_t len) 132 | { append(static_cast(data), len); } 133 | 134 | void append(const string &s) 135 | { append(s.c_str(), s.length()); } 136 | 137 | void append(const Buffer &s) 138 | { append(s.data(), s.length()); } 139 | 140 | void append(const Buffer *s) 141 | { append(s->data(), s->length()); } 142 | 143 | void assign(const void *data, size_t len) 144 | { 145 | clear(); 146 | append(data, len); 147 | } 148 | 149 | void assign(Buffer &rhs) 150 | { assign(rhs.data(), rhs.length()); } 151 | 152 | uint8_t* beginWrite() 153 | { return begin() + _writerIndex; } 154 | 155 | const uint8_t* beginWrite() const 156 | { return begin() + _writerIndex; } 157 | 158 | void hasWritten(size_t len) 159 | { 160 | assert(len <= writableBytes()); 161 | _writerIndex += len; 162 | } 163 | 164 | void unwrite(size_t len) 165 | { 166 | assert(len <= length()); 167 | _writerIndex -= len; 168 | } 169 | 170 | void resize(size_t len) 171 | { 172 | if (length() > len) 173 | _writerIndex = _readerIndex + len; 174 | else if (length() < len) 175 | append(len - length(), '\0'); 176 | } 177 | 178 | void appendUInt64(uint64_t x) 179 | { append(&x, sizeof(x)); } 180 | 181 | void appendUInt32(uint32_t x) 182 | { append(&x, sizeof(x)); } 183 | 184 | void appendUInt32Be(uint32_t x); 185 | 186 | void appendUInt16(uint16_t x) 187 | { append(&x, sizeof(x)); } 188 | 189 | void appendUInt16Be(uint16_t x); 190 | 191 | void appendUInt8(uint8_t x) 192 | { append(&x, sizeof(x)); } 193 | 194 | uint64_t readUInt64() 195 | { 196 | uint64_t result = peekUInt64(); 197 | retrieveUInt64(); 198 | return result; 199 | } 200 | 201 | /// Require: buf->length() >= sizeof(uint32_t) 202 | uint32_t readUInt32() 203 | { 204 | uint32_t result = peekUInt32(); 205 | retrieveUInt32(); 206 | return result; 207 | } 208 | 209 | uint32_t readUInt32Be(); 210 | 211 | uint16_t readUInt16() 212 | { 213 | uint16_t result = peekUInt16(); 214 | retrieveUInt16(); 215 | return result; 216 | } 217 | 218 | uint16_t readUInt16Be(); 219 | 220 | uint8_t readUInt8() 221 | { 222 | uint8_t result = peekUInt8(); 223 | retrieveUInt8(); 224 | return result; 225 | } 226 | 227 | uint64_t peekUInt64() const 228 | { 229 | assert(length() >= sizeof(uint64_t)); 230 | uint64_t x = 0; 231 | ::memcpy(&x, data(), sizeof(x)); 232 | return x; 233 | } 234 | /// Require: buf->length() >= sizeof(uint32_t) 235 | uint32_t peekUInt32() const 236 | { 237 | assert(length() >= sizeof(uint32_t)); 238 | uint32_t x = 0; 239 | ::memcpy(&x, data(), sizeof(x)); 240 | return x; 241 | } 242 | 243 | uint32_t peekInt32Be() const; 244 | 245 | uint16_t peekUInt16() const 246 | { 247 | assert(length() >= sizeof(uint16_t)); 248 | uint16_t x = 0; 249 | ::memcpy(&x, data(), sizeof(x)); 250 | return x; 251 | } 252 | 253 | uint16_t peekInt16Be() const; 254 | 255 | uint8_t peekUInt8() const 256 | { 257 | assert(length() >= sizeof(uint8_t)); 258 | uint8_t x = *data(); 259 | return x; 260 | } 261 | 262 | void prependUInt64(uint64_t x) 263 | { prepend(&x, sizeof(x)); } 264 | 265 | void prependUInt32(uint32_t x) 266 | { prepend(&x, sizeof(x)); } 267 | 268 | void prependUInt32Be(uint32_t x); 269 | 270 | void prependUInt16(uint16_t x) 271 | { prepend(&x, sizeof(x)); } 272 | 273 | void prependUInt16Be(uint16_t x); 274 | 275 | void prependUInt8(uint8_t x) 276 | { prepend(&x, sizeof x); } 277 | 278 | void prepend(const void* data, size_t len) 279 | { 280 | ensurePrependableBytes(len); 281 | _readerIndex -= len; 282 | const uint8_t *d = static_cast(data); 283 | std::copy(d, d+len, begin() + _readerIndex); 284 | } 285 | 286 | void prepend(const string &data) 287 | { 288 | prepend(data.c_str(), data.length()); 289 | } 290 | 291 | size_t internalCapacity() const 292 | { 293 | return _buffer.capacity(); 294 | } 295 | 296 | void ensureWritableBytes(size_t len) 297 | { 298 | if (writableBytes() >= len) 299 | return; 300 | 301 | _buffer.resize(_writerIndex + len); 302 | } 303 | 304 | void ensurePrependableBytes(size_t len) 305 | { 306 | if (prependableBytes() >= len) 307 | return; 308 | 309 | len += kCheapPrepend; 310 | 311 | if (prependableBytes() + writableBytes() < len) 312 | _buffer.resize(_writerIndex + len); 313 | 314 | size_t readable = length(); 315 | std::copy_backward(begin() + _readerIndex, 316 | begin() + _writerIndex, 317 | begin() + readable + len); 318 | _readerIndex = len; 319 | _writerIndex = _readerIndex + readable; 320 | assert(readable == length()); 321 | } 322 | 323 | private: 324 | uint8_t* begin() 325 | { return &*_buffer.begin(); } 326 | 327 | const uint8_t* begin() const 328 | { return &*_buffer.begin(); } 329 | 330 | std::vector _buffer; 331 | size_t _readerIndex; 332 | size_t _writerIndex; 333 | }; 334 | 335 | typedef shared_ptr BufferPtr; 336 | 337 | } // namespace rdpp 338 | 339 | #endif // _RDPP_CORE_BUFFER_H_ 340 | -------------------------------------------------------------------------------- /librdpp/core/config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/librdpp/core/config.h -------------------------------------------------------------------------------- /librdpp/core/crypto.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define TAG "CRYPTO" 9 | 10 | using namespace rdpp; 11 | 12 | bool Rsa::random(uint8_t *output, int len) 13 | { 14 | return (RAND_bytes(output, len) == 1); 15 | } 16 | 17 | bool Rsa::random(Buffer &output, int len) 18 | { 19 | int ret; 20 | 21 | output.clear(); 22 | output.ensureWritableBytes(len); 23 | 24 | ret = RAND_bytes((uint8_t *)output.beginWrite(), len); 25 | output.hasWritten(len); 26 | return (ret == 1); 27 | } 28 | 29 | string Rsa::random(int len) 30 | { 31 | string out(len, '\0'); 32 | if (RAND_bytes((uint8_t *)out.data(), len) == 1) 33 | return out; 34 | return ""; 35 | } 36 | 37 | static void binnum_to_bin(const BIGNUM *a, Buffer &output) 38 | { 39 | int len = BN_num_bytes(a); 40 | 41 | output.clear(); 42 | output.ensureWritableBytes(len); 43 | BN_bn2bin(a, (uint8_t *)output.beginWrite()); 44 | Rsa::crypto_reverse((uint8_t *)output.beginWrite(), len); 45 | output.hasWritten(len); 46 | } 47 | 48 | bool Rsa::generateKey(Buffer &n, Buffer &e, Buffer &d) 49 | { 50 | RSA *r = RSA_generate_key(512, RSA_F4, NULL, NULL); 51 | if (r) { 52 | binnum_to_bin(r->n, n); 53 | binnum_to_bin(r->e, e); 54 | binnum_to_bin(r->d, d); 55 | e.resize(4); 56 | RSA_free(r); 57 | return true; 58 | } 59 | return false; 60 | } 61 | 62 | int Rsa::rsa_common(const uint8_t* input, int length, uint32_t key_length, const uint8_t* modulus, const uint8_t* exponent, int exponent_size, uint8_t* output) 63 | { 64 | BN_CTX* ctx; 65 | int output_length = -1; 66 | uint8_t* input_reverse; 67 | uint8_t* modulus_reverse; 68 | uint8_t* exponent_reverse; 69 | BIGNUM *mod, *exp, *x, *y; 70 | 71 | input_reverse = (uint8_t*)malloc(2 * key_length + exponent_size); 72 | if (!input_reverse) 73 | return -1; 74 | 75 | modulus_reverse = input_reverse + key_length; 76 | exponent_reverse = modulus_reverse + key_length; 77 | 78 | memcpy(modulus_reverse, modulus, key_length); 79 | crypto_reverse(modulus_reverse, key_length); 80 | memcpy(exponent_reverse, exponent, exponent_size); 81 | crypto_reverse(exponent_reverse, exponent_size); 82 | memcpy(input_reverse, input, length); 83 | crypto_reverse(input_reverse, length); 84 | 85 | if (!(ctx = BN_CTX_new())) 86 | goto fail_bn_ctx; 87 | 88 | if (!(mod = BN_new())) 89 | goto fail_bn_mod; 90 | 91 | if (!(exp = BN_new())) 92 | goto fail_bn_exp; 93 | 94 | if (!(x = BN_new())) 95 | goto fail_bn_x; 96 | 97 | if (!(y = BN_new())) 98 | goto fail_bn_y; 99 | 100 | BN_bin2bn(modulus_reverse, key_length, mod); 101 | BN_bin2bn(exponent_reverse, exponent_size, exp); 102 | BN_bin2bn(input_reverse, length, x); 103 | BN_mod_exp(y, x, exp, mod, ctx); 104 | 105 | output_length = BN_bn2bin(y, output); 106 | crypto_reverse(output, output_length); 107 | 108 | if (output_length < (int)key_length) 109 | memset(output + output_length, 0, key_length - output_length); 110 | 111 | BN_free(y); 112 | fail_bn_y: 113 | BN_clear_free(x); 114 | fail_bn_x: 115 | BN_free(exp); 116 | fail_bn_exp: 117 | BN_free(mod); 118 | fail_bn_mod: 119 | BN_CTX_free(ctx); 120 | fail_bn_ctx: 121 | free(input_reverse); 122 | 123 | return output_length; 124 | } 125 | 126 | int Rsa::public_encrypt(const uint8_t* input, int length, uint32_t key_length, const uint8_t* modulus, const uint8_t* exponent, uint8_t* output) 127 | { 128 | return rsa_public(input, length, key_length, modulus, exponent, output); 129 | } 130 | 131 | int Rsa::public_decrypt(const uint8_t* input, int length, uint32_t key_length, const uint8_t* modulus, const uint8_t* exponent, uint8_t* output) 132 | { 133 | return rsa_public(input, length, key_length, modulus, exponent, output); 134 | } 135 | 136 | int Rsa::private_encrypt(const uint8_t* input, int length, uint32_t key_length, const uint8_t* modulus, const uint8_t* private_exponent, uint8_t* output) 137 | { 138 | return rsa_private(input, length, key_length, modulus, private_exponent, output); 139 | } 140 | 141 | int Rsa::private_decrypt(const uint8_t* input, int length, uint32_t key_length, const uint8_t* modulus, const uint8_t* private_exponent, uint8_t* output) 142 | { 143 | return rsa_private(input, length, key_length, modulus, private_exponent, output); 144 | } 145 | 146 | void Rsa::crypto_reverse(uint8_t* data, int length) 147 | { 148 | int i, j; 149 | uint8_t temp; 150 | 151 | for (i = 0, j = length - 1; i < j; i++, j--) { 152 | temp = data[i]; 153 | data[i] = data[j]; 154 | data[j] = temp; 155 | } 156 | } 157 | 158 | // 159 | // HMac 160 | // 161 | 162 | HMac::HMac() 163 | { 164 | #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) 165 | _ctx = calloc(1, sizeof(HMAC_CTX)); 166 | HMAC_CTX_init((HMAC_CTX *)_ctx); 167 | #else 168 | hmac = (void *)HMAC_CTX_new(); 169 | #endif 170 | } 171 | 172 | HMac::~HMac() 173 | { 174 | if (_ctx) { 175 | #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) 176 | HMAC_CTX_cleanup((HMAC_CTX *)_ctx); 177 | free(_ctx); 178 | #else 179 | HMAC_CTX_free((HMAC_CTX *)_ctx); 180 | #endif 181 | _ctx = NULL; 182 | } 183 | } 184 | 185 | bool HMac::init(const char *md, const void *key, int keylen) 186 | { 187 | const EVP_MD* evp = EVP_get_digestbyname(md); 188 | 189 | if (!evp || !_ctx) 190 | return false; 191 | #if (OPENSSL_VERSION_NUMBER < 0x10000000L) 192 | HMAC_Init_ex((HMAC_CTX *)_ctx, key, keylen, evp, NULL); /* no return value on OpenSSL 0.9.x */ 193 | return true; 194 | #else 195 | if (HMAC_Init_ex((HMAC_CTX *)_ctx, key, keylen, evp, NULL) == 1) 196 | return true; 197 | #endif 198 | return false; 199 | } 200 | 201 | bool HMac::update(const void *input, size_t ilen) 202 | { 203 | #if (OPENSSL_VERSION_NUMBER < 0x10000000L) 204 | HMAC_Update((HMAC_CTX *)_ctx, input, ilen); /* no return value on OpenSSL 0.9.x */ 205 | return true; 206 | #else 207 | if (HMAC_Update((HMAC_CTX *)_ctx, (uint8_t *)input, ilen) == 1) 208 | return true; 209 | #endif 210 | return false; 211 | } 212 | 213 | bool HMac::final(void *output, int olen) 214 | { 215 | #if (OPENSSL_VERSION_NUMBER < 0x10000000L) 216 | HMAC_Final((HMAC_CTX *)_ctx, output, NULL); /* no return value on OpenSSL 0.9.x */ 217 | return true; 218 | #else 219 | if (HMAC_Final((HMAC_CTX *)_ctx, (uint8_t *)output, NULL) == 1) 220 | return true; 221 | #endif 222 | return false; 223 | } 224 | 225 | bool HMac::HMAC(const char *md, const void *key, int keylen, 226 | const void *input, size_t ilen, 227 | void *output, int olen) 228 | { 229 | HMac hmac; 230 | if (!hmac.init(md, key, keylen)) 231 | return false; 232 | if (!hmac.update(input, ilen)) 233 | return false; 234 | return hmac.final(output, olen); 235 | } 236 | 237 | // 238 | // Digest 239 | // 240 | Digest::Digest() 241 | { 242 | #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) 243 | _ctx = (void *)EVP_MD_CTX_create(); 244 | #else 245 | _ctx = (void *)EVP_MD_CTX_new(); 246 | #endif 247 | } 248 | 249 | Digest::~Digest() 250 | { 251 | if (_ctx) { 252 | #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) 253 | EVP_MD_CTX_destroy((EVP_MD_CTX *)_ctx); 254 | #else 255 | EVP_MD_CTX_free((EVP_MD_CTX *)_ctx); 256 | #endif 257 | _ctx = NULL; 258 | } 259 | } 260 | 261 | bool Digest::init(const char *md) 262 | { 263 | const EVP_MD *evp = EVP_get_digestbyname(md); 264 | 265 | if (!_ctx || !evp) 266 | return false; 267 | if (EVP_DigestInit_ex((EVP_MD_CTX *)_ctx, evp, NULL) != 1) 268 | return false; 269 | return true; 270 | } 271 | 272 | bool Digest::update(const uint8_t *input, int ilen) 273 | { 274 | return (EVP_DigestUpdate((EVP_MD_CTX *)_ctx, input, ilen) == 1); 275 | } 276 | 277 | bool Digest::update(const string &input) 278 | { 279 | return update((uint8_t *)input.data(), input.length()); 280 | } 281 | 282 | bool Digest::final(uint8_t *output, int olen) 283 | { 284 | return (EVP_DigestFinal_ex((EVP_MD_CTX *)_ctx, output, NULL) == 1); 285 | } 286 | 287 | bool Digest::digest(const char *md, const uint8_t *input, int ilen, uint8_t *output, int olen) 288 | { 289 | Digest ctx; 290 | 291 | if (!ctx.init(md)) 292 | return false; 293 | if(!ctx.update(input, ilen)) 294 | return false; 295 | if (!ctx.final(output, olen)) 296 | return false; 297 | return true; 298 | } 299 | 300 | bool Digest::MD4(const uint8_t *input, int ilen, uint8_t *output, int olen) 301 | { 302 | return digest("md4", input, ilen, output, olen); 303 | } 304 | 305 | bool Digest::MD5(const uint8_t *input, int ilen, uint8_t *output, int olen) 306 | { 307 | return digest("md5", input, ilen, output, olen); 308 | } 309 | 310 | 311 | // 312 | // Rc4 313 | // 314 | 315 | Rc4::Rc4() 316 | : _ctx(NULL) 317 | {} 318 | 319 | Rc4::~Rc4() 320 | { 321 | freeCtx(); 322 | } 323 | 324 | bool Rc4::setup(const uint8_t *key, int keylen) 325 | { 326 | freeCtx(); 327 | 328 | if (!key || (keylen == 0)) 329 | return false; 330 | if (!(_ctx = calloc(1, sizeof(RC4_KEY)))) 331 | return false; 332 | RC4_set_key((RC4_KEY *)_ctx, keylen, key); 333 | return true; 334 | } 335 | 336 | bool Rc4::update(int length, const uint8_t *input, uint8_t *output) 337 | { 338 | RC4((RC4_KEY *)_ctx, length, input, output); 339 | return true; 340 | } 341 | 342 | void Rc4::freeCtx() 343 | { 344 | if (_ctx) { 345 | memset(_ctx, 0, sizeof(RC4_KEY)); 346 | free(_ctx); 347 | _ctx = NULL; 348 | } 349 | } 350 | 351 | bool Rc4::rc4k(const uint8_t *key, int keylen, 352 | int length, const uint8_t *input, uint8_t *output) 353 | { 354 | Rc4 rc4; 355 | if (!rc4.setup(key, keylen)) 356 | return false; 357 | if (!rc4.update(length, input, output)) 358 | return false; 359 | return true; 360 | } 361 | 362 | // 363 | // Cipher 364 | // 365 | 366 | Cipher::Cipher() 367 | { 368 | _ctx = (void *)EVP_CIPHER_CTX_new(); 369 | } 370 | 371 | Cipher::~Cipher() 372 | { 373 | if (_ctx) { 374 | EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)_ctx); 375 | _ctx = NULL; 376 | } 377 | } 378 | 379 | bool Cipher::init(const char *cipher, bool encrypt, const uint8_t *key, const uint8_t *iv) 380 | { 381 | const EVP_CIPHER *evp = EVP_get_cipherbyname(cipher); 382 | EVP_CIPHER_CTX *octx = (EVP_CIPHER_CTX *)_ctx; 383 | int enc = encrypt ? 1 : 0; 384 | 385 | if (!_ctx || !evp) 386 | return false; 387 | if (EVP_CipherInit_ex(octx, evp, NULL, key, iv, enc) != 1) 388 | return false; 389 | EVP_CIPHER_CTX_set_padding(octx, 0); 390 | _ctx = (void *)octx; 391 | return true; 392 | } 393 | 394 | bool Cipher::update(const uint8_t *input, int ilen, uint8_t *output, int *olen) 395 | { 396 | return (EVP_CipherUpdate((EVP_CIPHER_CTX *)_ctx, output, olen, input, ilen) == 1); 397 | } 398 | 399 | bool Cipher::final(uint8_t *output, int *olen) 400 | { 401 | return (EVP_CipherFinal_ex((EVP_CIPHER_CTX *)_ctx, output, olen) == 1); 402 | } 403 | -------------------------------------------------------------------------------- /librdpp/core/crypto.h: -------------------------------------------------------------------------------- 1 | #ifndef _RDPP_CORE_CRYPTO_H_ 2 | #define _RDPP_CORE_CRYPTO_H_ 3 | 4 | #include 5 | #include 6 | 7 | namespace rdpp { 8 | 9 | inline void security_uint32_le(uint8_t *output, uint32_t value) 10 | { 11 | output[0] = (value) & 0xFF; 12 | output[1] = (value >> 8) & 0xFF; 13 | output[2] = (value >> 16) & 0xFF; 14 | output[3] = (value >> 24) & 0xFF; 15 | } 16 | 17 | inline void security_uint64_le(uint8_t *output, uint64_t value) 18 | { 19 | output[0] = (value) & 0xFF; 20 | output[1] = (value >> 8) & 0xFF; 21 | output[2] = (value >> 16) & 0xFF; 22 | output[3] = (value >> 24) & 0xFF; 23 | output[4] = (value >> 32) & 0xFF; 24 | output[5] = (value >> 40) & 0xFF; 25 | output[6] = (value >> 48) & 0xFF; 26 | output[7] = (value >> 56) & 0xFF; 27 | } 28 | 29 | class Rsa 30 | { 31 | public: 32 | static const uint32_t EXPONENT_MAX_SIZE = 4; 33 | static const uint32_t TSSK_KEY_LENGTH = 64; 34 | 35 | static bool random(uint8_t *output, int len); 36 | static bool random(Buffer &output, int len); 37 | static string random(int len); 38 | static bool generateKey(Buffer &n, Buffer &e, Buffer &d); 39 | static int public_encrypt(const uint8_t* input, int length, uint32_t key_length, const uint8_t* modulus, const uint8_t* exponent, uint8_t* output); 40 | static int public_decrypt(const uint8_t* input, int length, uint32_t key_length, const uint8_t* modulus, const uint8_t* exponent, uint8_t* output); 41 | static int private_encrypt(const uint8_t* input, int length, uint32_t key_length, const uint8_t* modulus, const uint8_t* private_exponent, uint8_t* output); 42 | static int private_decrypt(const uint8_t* input, int length, uint32_t key_length, const uint8_t* modulus, const uint8_t* private_exponent, uint8_t* output); 43 | static void crypto_reverse(uint8_t *data, int length); 44 | private: 45 | static int rsa_common(const uint8_t* input, int length, uint32_t key_length, const uint8_t* modulus, const uint8_t* exponent, int exponent_size, uint8_t* output); 46 | static int rsa_public(const uint8_t* input, int length, uint32_t key_length, const uint8_t* modulus, const uint8_t* exponent, uint8_t* output) 47 | { 48 | return rsa_common(input, length, key_length, modulus, exponent, EXPONENT_MAX_SIZE, output); 49 | } 50 | static int rsa_private(const uint8_t* input, int length, uint32_t key_length, const uint8_t* modulus, const uint8_t* private_exponent, uint8_t* output) 51 | { 52 | return rsa_common(input, length, key_length, modulus, private_exponent, key_length, output); 53 | } 54 | }; 55 | 56 | class HMac 57 | { 58 | public: 59 | HMac(); 60 | ~HMac(); 61 | bool init(const char *md, const void *key, int keylen); 62 | bool update(const void *input, size_t ilen); 63 | bool final(void *output, int olen); 64 | static bool HMAC(const char *md, const void *key, int keylen, 65 | const void *input, size_t ilen, 66 | void *output, int olen); 67 | private: 68 | void *_ctx; 69 | }; 70 | 71 | class Digest 72 | { 73 | public: 74 | static const int SHA1_LENGTH = 20; 75 | static const int MD5_DIGEST_LENGTH = 16; 76 | static const int MD4_DIGEST_LENGTH = 16; 77 | 78 | Digest(); 79 | ~Digest(); 80 | bool init(const char *md); 81 | bool update(const uint8_t *input, int ilen); 82 | bool update(const string &input); 83 | bool final(uint8_t *output, int olen); 84 | static bool digest(const char *md, const uint8_t *input, 85 | int ilen, uint8_t *output, int olen); 86 | static bool MD4(const uint8_t *input, int ilen, uint8_t *output, int olen); 87 | static bool MD5(const uint8_t *input, int ilen, uint8_t *output, int olen); 88 | private: 89 | void *_ctx; 90 | }; 91 | 92 | class Rc4 93 | { 94 | public: 95 | Rc4(); 96 | ~Rc4(); 97 | bool setup(const uint8_t *key, int keylen); 98 | bool update(int length, const uint8_t *input, uint8_t *output); 99 | static bool rc4k(const uint8_t *key, int keylen, 100 | int length, const uint8_t *input, uint8_t *output); 101 | private: 102 | void freeCtx(); 103 | void *_ctx; 104 | }; 105 | 106 | class Cipher 107 | { 108 | public: 109 | Cipher(); 110 | ~Cipher(); 111 | bool init(const char *cipher, bool encrypt, const uint8_t *key, const uint8_t *iv); 112 | bool update(const uint8_t *input, int ilen, uint8_t *output, int *olen); 113 | bool final(uint8_t *output, int *olen); 114 | private: 115 | void *_ctx; 116 | }; 117 | 118 | } // namespace rdpp 119 | 120 | #endif // _RDPP_CORE_CRYPTO_H_ 121 | -------------------------------------------------------------------------------- /librdpp/core/layer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/librdpp/core/layer.h -------------------------------------------------------------------------------- /librdpp/core/log.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace rdpp { 9 | namespace detail { 10 | 11 | 12 | // 日志级别 13 | const char* LogLevelName[LOGLEVEL_NUM_LOG_LEVELS] = { 14 | "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", 15 | }; 16 | 17 | //默认的日志输出函数 18 | void nullLogHandler(const string &message) 19 | { 20 | // Nothing. 21 | } 22 | 23 | static LogLevel g_logLevel = LOGLEVEL_TRACE; 24 | static LogHandler g_logHandler = nullLogHandler; 25 | static std::map g_logTags; 26 | 27 | 28 | // 高效的整型转字符串算法 by Matthew Wilson. 29 | const char digits[] = "9876543210123456789"; 30 | const char* zero = digits + 9; 31 | const char digitsHex[] = "0123456789ABCDEF"; 32 | 33 | template 34 | inline size_t convert(char buf[], T value) 35 | { 36 | T i = value; 37 | char* p = buf; 38 | 39 | do { 40 | int lsd = static_cast(i % 10); 41 | i /= 10; 42 | *p++ = zero[lsd]; 43 | } while (i != 0); 44 | 45 | if (value < 0) 46 | *p++ = '-'; 47 | *p = '\0'; 48 | std::reverse(buf, p); 49 | 50 | return p - buf; 51 | } 52 | 53 | inline size_t convertHex(char buf[], uintptr_t value) 54 | { 55 | uintptr_t i = value; 56 | char* p = buf; 57 | 58 | do { 59 | int lsd = static_cast(i % 16); 60 | i /= 16; 61 | *p++ = digitsHex[lsd]; 62 | } while (i != 0); 63 | 64 | *p = '\0'; 65 | std::reverse(buf, p); 66 | 67 | return p - buf; 68 | } 69 | 70 | LogMessage::LogMessage(LogLevel level, const char *tag, const char *filename, int line) 71 | : _level(level) 72 | { 73 | *this << "[" 74 | << Timestamp::now().toFormatString() << " " 75 | << LogLevelName[level] << " " 76 | << filename << ":" << line << " " 77 | << tag 78 | << "] "; 79 | } 80 | 81 | LogMessage::~LogMessage() 82 | {} 83 | 84 | LogMessage &LogMessage::operator<<(const string &value) 85 | { 86 | _message += value; 87 | return *this; 88 | } 89 | 90 | LogMessage &LogMessage::operator<<(const char* value) 91 | { 92 | _message += value; 93 | return *this; 94 | } 95 | 96 | #undef DECLARE_STREAM_FORMAT_INTEGER 97 | #define DECLARE_STREAM_FORMAT_INTEGER(TYPE) \ 98 | LogMessage& LogMessage::operator<<(TYPE value) \ 99 | { \ 100 | char buffer[128]; \ 101 | convert(buffer, value); \ 102 | buffer[sizeof(buffer) - 1] = '\0'; \ 103 | _message += buffer; \ 104 | return *this; \ 105 | } 106 | 107 | DECLARE_STREAM_FORMAT_INTEGER(char) 108 | DECLARE_STREAM_FORMAT_INTEGER(int) 109 | DECLARE_STREAM_FORMAT_INTEGER(unsigned int) 110 | DECLARE_STREAM_FORMAT_INTEGER(long) 111 | DECLARE_STREAM_FORMAT_INTEGER(unsigned long) 112 | DECLARE_STREAM_FORMAT_INTEGER(long long) 113 | DECLARE_STREAM_FORMAT_INTEGER(unsigned long long) 114 | #undef DECLARE_STREAM_OPERATOR 115 | 116 | LogMessage &LogMessage::operator<<(double value) 117 | { 118 | char buffer[128]; 119 | snprintf(buffer, sizeof(buffer), "%g", value); 120 | buffer[sizeof(buffer) - 1] = '\0'; 121 | _message += buffer; 122 | return *this; 123 | } 124 | 125 | LogMessage &LogMessage::operator<<(const void* p) 126 | { 127 | uintptr_t v = reinterpret_cast(p); 128 | char buffer[128]; 129 | buffer[0] = '0'; 130 | buffer[1] = 'x'; 131 | convertHex(buffer + 2, v); 132 | buffer[sizeof(buffer) - 1] = '\0'; 133 | _message += buffer; 134 | return *this; 135 | } 136 | 137 | void LogMessage::finish() 138 | { 139 | g_logHandler(_message); 140 | 141 | if (LOGLEVEL_FATAL == _level) 142 | abort(); 143 | } 144 | 145 | void LogFinisher::operator=(LogMessage& other) 146 | { 147 | other.finish(); 148 | } 149 | 150 | } // namespace detail 151 | 152 | // 设置日志写函数 153 | void setLogHandler(LogHandler newFunc) 154 | { 155 | if (NULL == newFunc) { 156 | detail::g_logHandler = rdpp::bind(detail::nullLogHandler, _1); 157 | } else { 158 | detail::g_logHandler = newFunc; 159 | } 160 | } 161 | 162 | // 设置日志级别 163 | void setLogLevel(const char *tag, LogLevel level) 164 | { 165 | if (tag == NULL) { 166 | detail::g_logLevel = level; 167 | std::map::iterator it; 168 | for (it = detail::g_logTags.begin(); it != detail::g_logTags.end(); ++it) 169 | it->second = level; 170 | } else { 171 | detail::g_logTags[tag] = level; 172 | } 173 | } 174 | 175 | LogLevel logLevel(const char *tag) 176 | { 177 | std::map::iterator it = detail::g_logTags.find(tag); 178 | if (it != detail::g_logTags.end()) { 179 | return it->second; 180 | } else { 181 | detail::g_logTags[tag] = detail::g_logLevel; 182 | return detail::g_logLevel; 183 | } 184 | } 185 | 186 | string hexdump(const Buffer &s) 187 | { 188 | return hexdump(s.data(), s.length()); 189 | } 190 | 191 | string hexdump(const Buffer *s) 192 | { 193 | return hexdump(s->data(), s->length()); 194 | } 195 | 196 | string hexdump(const string &data) 197 | { 198 | return hexdump(data.c_str(), data.length()); 199 | } 200 | 201 | string hexdump(const void *data, size_t len) 202 | { 203 | static char *b2h = "0123456789ABCDEF"; 204 | string output = StringUtil::format("\nhexdump(addr:0x%x, len:%d):\n", data, len); 205 | const char *_data = (const char *)data; 206 | unsigned char line[48 + 16 + 1]; // each line 207 | int pos, linesize; 208 | char c; 209 | 210 | for (size_t i = 0; i < len; i += 16) { 211 | if (len - i < 16) 212 | linesize = len - i; 213 | else 214 | linesize = 16; 215 | 216 | memset(line, ' ', sizeof(line)); 217 | pos = 0; 218 | 219 | for (int j = 0; j < 16; j++) { 220 | c = _data[i+j]; 221 | 222 | if (j < linesize) { 223 | line[pos] = b2h[(c & 0xf0) >> 4]; 224 | line[pos+1] = b2h[c & 0x0f]; 225 | } 226 | 227 | pos += 3; 228 | } 229 | 230 | for (int j = 0; j < linesize; j++) { 231 | c = _data[i+j]; 232 | 233 | if (c >= 0x20 && c <= 0x7e) 234 | line[pos++] = c; 235 | else 236 | line[pos++] = '.'; 237 | } 238 | 239 | line[pos] = '\0'; 240 | 241 | output += StringUtil::format("%04X: %s\n", i, line); 242 | } 243 | return output; 244 | } 245 | 246 | } // namespace rdpp 247 | -------------------------------------------------------------------------------- /librdpp/core/log.h: -------------------------------------------------------------------------------- 1 | #ifndef _RDPP_CORE_LOG_H_ 2 | #define _RDPP_CORE_LOG_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace rdpp { 10 | 11 | enum LogLevel { 12 | LOGLEVEL_TRACE, 13 | LOGLEVEL_DEBUG, 14 | LOGLEVEL_INFO, 15 | LOGLEVEL_WARN, 16 | LOGLEVEL_ERROR, 17 | LOGLEVEL_FATAL, 18 | LOGLEVEL_NUM_LOG_LEVELS 19 | }; 20 | 21 | namespace detail { 22 | 23 | // 从路径中得到文件名 24 | inline const char *getFileNameFromPath(const char *pathName) 25 | { 26 | const char* slash = strrchr(pathName, '/'); 27 | if (slash) { 28 | return slash + 1; 29 | } else { 30 | const char *bslash = strrchr(pathName, '\\'); 31 | if (bslash) { 32 | return bslash + 1; 33 | } 34 | } 35 | return pathName; 36 | } 37 | 38 | class LogFinisher; 39 | 40 | class LogMessage 41 | { 42 | public: 43 | LogMessage(LogLevel level, const char *tag, const char *filename, int line); 44 | ~LogMessage(); 45 | 46 | LogMessage &operator<<(const string &value); 47 | LogMessage &operator<<(const char *value); 48 | LogMessage &operator<<(char value); 49 | LogMessage &operator<<(int value); 50 | LogMessage &operator<<(unsigned int value); 51 | LogMessage &operator<<(long value); 52 | LogMessage &operator<<(unsigned long value); 53 | LogMessage &operator<<(long long value); 54 | LogMessage &operator<<(unsigned long long value); 55 | LogMessage &operator<<(double value); 56 | LogMessage &operator<<(const void *p); 57 | 58 | private: 59 | friend class LogFinisher; 60 | friend class LogTraceFunction; 61 | void finish(); 62 | 63 | LogLevel _level; 64 | string _message; 65 | }; 66 | 67 | class LogFinisher 68 | { 69 | public: 70 | void operator=(LogMessage &other); 71 | }; 72 | 73 | } // namespace detail 74 | 75 | typedef rdpp::function LogHandler; 76 | 77 | void setLogHandler(LogHandler newFunc); 78 | 79 | void setLogLevel(const char *tag, LogLevel level); 80 | LogLevel logLevel(const char *tag); 81 | 82 | #undef ERROR 83 | 84 | #define RDPP_LOG(TAG, LEVEL) if (rdpp::logLevel(TAG) <= rdpp::LOGLEVEL_##LEVEL) \ 85 | rdpp::detail::LogFinisher() = \ 86 | rdpp::detail::LogMessage(rdpp::LOGLEVEL_##LEVEL, TAG, \ 87 | rdpp::detail::getFileNameFromPath(__FILE__), __LINE__) 88 | #define RDPP_LOG_IF(TAG, LEVEL, CONDITION) \ 89 | !(CONDITION) ? (void)0 : RDPP_LOG(TAG, LEVEL) 90 | 91 | class Buffer; 92 | string hexdump(const Buffer &s); 93 | string hexdump(const Buffer *s); 94 | string hexdump(const string &s); 95 | string hexdump(const void *data, size_t len); 96 | 97 | } // namespace rdpp 98 | 99 | #endif // _RDPP_CORE_LOG_H_ 100 | -------------------------------------------------------------------------------- /librdpp/core/poppack.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Module Name: 6 | 7 | poppack.h 8 | 9 | Abstract: 10 | 11 | This file turns packing of structures off. (That is, it enables 12 | automatic alignment of structure fields.) An include file is needed 13 | because various compilers do this in different ways. 14 | 15 | poppack.h is the complement to pshpack?.h. An inclusion of poppack.h 16 | MUST ALWAYS be preceded by an inclusion of one of pshpack?.h, in one-to-one 17 | correspondence. 18 | 19 | For Microsoft compatible compilers, this file uses the pop option 20 | to the pack pragma so that it can restore the previous saved by the 21 | pshpack?.h include file. 22 | 23 | --*/ 24 | 25 | #if ! (defined(lint) || defined(RC_INVOKED)) 26 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 27 | #pragma warning(disable:4103) 28 | #if !(defined( MIDL_PASS )) || defined( __midl ) 29 | #pragma pack(pop) 30 | #else 31 | #pragma pack() 32 | #endif 33 | #else 34 | #pragma pack() 35 | #endif 36 | #endif /* ! (defined(lint) || defined(RC_INVOKED)) */ 37 | 38 | -------------------------------------------------------------------------------- /librdpp/core/pshpack1.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Module Name: 6 | 7 | pshpack1.h 8 | 9 | Abstract: 10 | 11 | This file turns 1 byte packing of structures on. (That is, it disables 12 | automatic alignment of structure fields.) An include file is needed 13 | because various compilers do this in different ways. For Microsoft 14 | compatible compilers, this files uses the push option to the pack pragma 15 | so that the poppack.h include file can restore the previous packing 16 | reliably. 17 | 18 | The file poppack.h is the complement to this file. 19 | 20 | --*/ 21 | 22 | #if ! (defined(lint) || defined(RC_INVOKED)) 23 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 24 | #pragma warning(disable:4103) 25 | #if !(defined( MIDL_PASS )) || defined( __midl ) 26 | #pragma pack(push,1) 27 | #else 28 | #pragma pack(1) 29 | #endif 30 | #else 31 | #pragma pack(1) 32 | #endif 33 | #endif /* ! (defined(lint) || defined(RC_INVOKED)) */ 34 | 35 | -------------------------------------------------------------------------------- /librdpp/core/rss.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define TAG "RSS" 5 | 6 | using namespace rdpp; 7 | 8 | // 9 | // FileRecorder 10 | // 11 | 12 | FileRecorder::FileRecorder(const string &filename) 13 | : _fp(::fopen(filename.data(), "wb")) 14 | , _lastEventTimer(Timestamp::now()) 15 | { 16 | RDPP_LOG(TAG, INFO) << "RSS Filename: " << filename; 17 | 18 | ::setvbuf(_fp, _buffer, _IOFBF, sizeof(_buffer)); 19 | 20 | RssHeader hdr; 21 | hdr.timestamp = _lastEventTimer.timestamp(); 22 | 23 | write(&hdr, sizeof(hdr)); 24 | } 25 | 26 | FileRecorder::~FileRecorder() 27 | { 28 | if (_fp) { 29 | ::fclose(_fp); 30 | _fp = NULL; 31 | } 32 | } 33 | 34 | bool FileRecorder::rec(uint16_t eventType, const Buffer &eventData) 35 | { 36 | Event hdr; 37 | Timestamp now(Timestamp::now()); 38 | 39 | hdr.type = eventType; 40 | hdr.length = sizeof(hdr) + eventData.length(); 41 | hdr.timestemp = (uint32_t)(now.timestamp() - _lastEventTimer.timestamp()); 42 | _lastEventTimer = now; 43 | 44 | if (!write(&hdr, sizeof(hdr))) 45 | return false; 46 | if (!write(eventData.data(), eventData.length())) 47 | return false; 48 | 49 | if (hdr.timestemp >= _kFlushPerMilliSeconds) 50 | ::fflush(_fp); 51 | 52 | return true; 53 | } 54 | 55 | bool FileRecorder::update(uint16_t destLeft, uint16_t destTop, 56 | uint16_t destRight, uint16_t destBottom, 57 | uint16_t width, uint16_t height, uint8_t bpp, 58 | uint8_t upateFormat, const string &data) 59 | { 60 | Buffer s; 61 | UpdateEvent updateEvent; 62 | 63 | updateEvent.destLeft = destLeft; 64 | updateEvent.destTop = destTop; 65 | updateEvent.destRight = destRight; 66 | updateEvent.destBottom = destBottom; 67 | updateEvent.width = width; 68 | updateEvent.height = height; 69 | updateEvent.bpp = bpp; 70 | updateEvent.format = upateFormat; 71 | updateEvent.length = data.length(); 72 | updateEvent.data = data; 73 | 74 | updateEvent.write(s); 75 | 76 | return rec(RSS_EVENT_UPDATE, s); 77 | } 78 | 79 | bool FileRecorder::screen(uint16_t width, uint16_t height, uint8_t colorDepth) 80 | { 81 | Buffer s; 82 | ScreenEvent screenEvent; 83 | 84 | screenEvent.width = width; 85 | screenEvent.height = height; 86 | screenEvent.colorDepth = colorDepth; 87 | 88 | s.append(&screenEvent, sizeof(screenEvent)); 89 | 90 | return rec(RSS_EVENT_SCREEN, s); 91 | } 92 | 93 | bool FileRecorder::credentials(const string &username, const string &password, 94 | const string &domain, const string &hostname) 95 | { 96 | Buffer s; 97 | InfoEvent infoEvent; 98 | 99 | infoEvent.usernameLength = username.length(); 100 | infoEvent.username = username; 101 | infoEvent.passwordLength = password.length(); 102 | infoEvent.password = password; 103 | infoEvent.domainLength = domain.length(); 104 | infoEvent.domain = domain; 105 | infoEvent.hostnameLength = hostname.length(); 106 | infoEvent.hostname = hostname; 107 | 108 | infoEvent.write(s); 109 | 110 | return rec(RSS_EVENT_INFO, s); 111 | } 112 | 113 | 114 | bool FileRecorder::keyUnicode(uint32_t code, uint8_t isPressed) 115 | { 116 | Buffer s; 117 | KeyEventUnicode keyEvent; 118 | 119 | keyEvent.code = code; 120 | keyEvent.isPressed = isPressed; 121 | 122 | s.append(&keyEvent, sizeof(keyEvent)); 123 | 124 | return rec(RSS_EVENT_KEY_UNICODE, s); 125 | } 126 | 127 | 128 | bool FileRecorder::keyScancode(uint32_t code, uint8_t isPressed) 129 | { 130 | Buffer s; 131 | KeyEventScancode keyEvent; 132 | 133 | keyEvent.code = code; 134 | keyEvent.isPressed = isPressed; 135 | 136 | s.append(&keyEvent, sizeof(keyEvent)); 137 | 138 | return rec(RSS_EVENT_KEY_SCANCODE, s); 139 | } 140 | 141 | bool FileRecorder::close(void) 142 | { 143 | Buffer s; 144 | return rec(RSS_EVENT_CLOSE, s); 145 | } 146 | 147 | bool FileRecorder::write(const void *data, size_t len) 148 | { 149 | if (!_fp) 150 | return false; 151 | if (!data || len == 0) 152 | return true; 153 | 154 | const char *p = (const char *)data; 155 | 156 | size_t n = ::fwrite(p, 1, len, _fp); 157 | size_t remain = len - n; 158 | while (remain > 0) { 159 | size_t x = ::fwrite(p + n, 1, remain, _fp); 160 | if (x == 0) { 161 | int err = ::ferror(_fp); 162 | if (err) 163 | return false; 164 | break; 165 | } 166 | n += x; 167 | remain = len - n; 168 | } 169 | return true; 170 | } 171 | 172 | // 173 | // FileReader 174 | // 175 | 176 | FileReader::FileReader(const string &filename) 177 | : _fp(::fopen(filename.data(), "rb")) 178 | { 179 | } 180 | 181 | FileReader::~FileReader() 182 | { 183 | ::fclose(_fp); 184 | } 185 | 186 | bool FileReader::header(RssHeader *hdr) 187 | { 188 | return read(hdr, sizeof(RssHeader)); 189 | } 190 | 191 | bool FileReader::nextEvent(Event *e, Buffer *eventData) 192 | { 193 | if (!read(e, sizeof(Event))) 194 | return false; 195 | 196 | size_t dataLength = e->length - sizeof(Event); 197 | 198 | eventData->clear(); 199 | eventData->ensureWritableBytes(dataLength); 200 | if (!read(eventData->beginWrite(), dataLength)) 201 | return false; 202 | 203 | eventData->hasWritten(dataLength); 204 | return true; 205 | } 206 | 207 | bool FileReader::read(void *buf, size_t len) 208 | { 209 | if (!buf || len == 0) 210 | return true; 211 | 212 | char *p = (char *)buf; 213 | 214 | size_t n = ::fread(p, 1, len, _fp); 215 | size_t remain = len - n; 216 | while (remain > 0) { 217 | size_t x = ::fread(p + n, 1, remain, _fp); 218 | if (x == 0) { 219 | int err = ::ferror(_fp); 220 | if (err) 221 | return false; 222 | break; 223 | } 224 | n += x; 225 | remain = len -n; 226 | } 227 | return true; 228 | } 229 | -------------------------------------------------------------------------------- /librdpp/core/rss.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Remote Session Scenario File format 3 | * Private protocol format to save events 4 | */ 5 | 6 | #ifndef _RDPP_CORE_RSS_H_ 7 | #define _RDPP_CORE_RSS_H_ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef WIN32 15 | #else 16 | #include 17 | #endif 18 | 19 | namespace rdpp { 20 | 21 | #include 22 | 23 | /// @summary: event type 24 | enum EventType { 25 | RSS_EVENT_UPDATE = 0x0001, 26 | RSS_EVENT_SCREEN = 0x0002, 27 | RSS_EVENT_INFO = 0x0003, 28 | RSS_EVENT_CLOSE = 0x0004, 29 | RSS_EVENT_KEY_UNICODE = 0x0005, 30 | RSS_EVENT_KEY_SCANCODE = 0x0006, 31 | }; 32 | 33 | /// @summary: format of update bitmap 34 | enum UpdateFormat { 35 | RSS_UPDATE_RAW = 0x01, 36 | RSS_UPDATE_BMP = 0x02, 37 | }; 38 | 39 | struct RssHeader { 40 | uint32_t magic; 41 | uint8_t version; 42 | uint64_t timestamp; 43 | 44 | RssHeader() : magic('RSS\0'), version(1) {} 45 | }; 46 | 47 | struct Event { 48 | uint16_t type; 49 | uint32_t timestemp; 50 | uint32_t length; 51 | }; 52 | 53 | /// @summary: Update event 54 | struct UpdateEvent { 55 | uint16_t destLeft; 56 | uint16_t destTop; 57 | uint16_t destRight; 58 | uint16_t destBottom; 59 | uint16_t width; 60 | uint16_t height; 61 | uint8_t bpp; 62 | uint8_t format; 63 | uint32_t length; // data length 64 | string data; 65 | 66 | void read(Buffer &s) 67 | { 68 | destLeft = s.readUInt16(); 69 | destTop = s.readUInt16(); 70 | destRight = s.readUInt16(); 71 | destBottom = s.readUInt16(); 72 | width = s.readUInt16(); 73 | height = s.readUInt16(); 74 | bpp = s.readUInt8(); 75 | format = s.readUInt8(); 76 | length = s.readUInt32(); 77 | data = s.retrieveAsString(length); 78 | } 79 | 80 | void write(Buffer &s) 81 | { 82 | assert(length == data.length()); 83 | 84 | s.appendUInt16(destLeft); 85 | s.appendUInt16(destTop); 86 | s.appendUInt16(destRight); 87 | s.appendUInt16(destBottom); 88 | s.appendUInt16(width); 89 | s.appendUInt16(height); 90 | s.appendUInt8(bpp); 91 | s.appendUInt8(format); 92 | s.appendUInt32(length); 93 | s.append(data); 94 | } 95 | }; 96 | 97 | /// @summary: Info event 98 | struct InfoEvent { 99 | uint16_t usernameLength; 100 | string username; 101 | uint16_t passwordLength; 102 | string password; 103 | uint16_t domainLength; 104 | string domain; 105 | uint16_t hostnameLength; 106 | string hostname; 107 | 108 | void read(Buffer &s) 109 | { 110 | usernameLength = s.readUInt16(); 111 | username = s.retrieveAsString(usernameLength); 112 | passwordLength = s.readUInt16(); 113 | password = s.retrieveAsString(passwordLength); 114 | domainLength = s.readUInt16(); 115 | domain = s.retrieveAsString(domainLength); 116 | hostnameLength = s.readUInt16(); 117 | hostname = s.retrieveAsString(hostnameLength); 118 | } 119 | 120 | void write(Buffer &s) 121 | { 122 | assert(usernameLength == username.length()); 123 | assert(passwordLength == password.length()); 124 | assert(domainLength == domain.length()); 125 | assert(hostnameLength == hostname.length()); 126 | 127 | s.appendUInt16(usernameLength); 128 | s.append(username); 129 | s.appendUInt16(passwordLength); 130 | s.append(password); 131 | s.appendUInt16(domainLength); 132 | s.append(domain); 133 | s.appendUInt16(hostnameLength); 134 | s.append(hostname); 135 | } 136 | }; 137 | 138 | /// @summary: screen information event 139 | struct ScreenEvent { 140 | uint16_t width; 141 | uint16_t height; 142 | uint8_t colorDepth; 143 | }; 144 | 145 | /// @summary: end of session event 146 | struct CloseEvent { 147 | }; 148 | 149 | /// @summary: keyboard event (keylogger) as unicode event 150 | struct KeyEventUnicode { 151 | uint32_t code; 152 | uint8_t isPressed; 153 | }; 154 | 155 | /// @summary: keyboard event (keylogger) 156 | struct KeyEventScancode { 157 | uint32_t code; 158 | uint8_t isPressed; 159 | }; 160 | 161 | #include 162 | 163 | /// @summary: RSS File recorder 164 | class FileRecorder 165 | { 166 | public: 167 | /// @param f : {file} file pointer use to write 168 | FileRecorder(const string &filename); 169 | ~FileRecorder(); 170 | 171 | /// @summary: save event in file 172 | bool rec(uint16_t eventType, const Buffer &eventData); 173 | 174 | /// @summary: record update event 175 | /// @param destLeft: {int} xmin position 176 | /// @param destTop : {int} ymin position 177 | /// @param destRight : {int} xmax position because RDP can send bitmap with padding 178 | /// @param destBottom : {int} ymax position because RDP can send bitmap with padding 179 | /// @param width : {int} width of bitmap 180 | /// @param height : {int} height of bitmap 181 | /// @param bpp : {int} number of bit per pixel 182 | /// @param upateFormat : {UpdateFormat} use RLE compression 183 | /// @param data : {str} bitmap data 184 | bool update(uint16_t destLeft, uint16_t destTop, 185 | uint16_t destRight, uint16_t destBottom, 186 | uint16_t width, uint16_t height, uint8_t bpp, 187 | uint8_t upateFormat, const string &data); 188 | 189 | /// @summary: record resize event of screen(maybe first event) 190 | /// @param width: {int} width of screen 191 | /// @param height : {int} height of screen 192 | /// @param colorDepth : {int} colorDepth 193 | bool screen(uint16_t width, uint16_t height, uint8_t colorDepth); 194 | 195 | /// @summary: Record informations event 196 | /// @param username: {str} username of session 197 | /// @param password : {str} password of session 198 | /// @param domain : {str} domain of session 199 | /// @param hostname : {str} hostname of session 200 | bool credentials(const string &username, const string & password, 201 | const string &domain = "", const string &hostname = ""); 202 | 203 | /// @summary: record key event as unicode 204 | /// @param code: unicode code 205 | /// @param isPressed : True if a key press event 206 | bool keyUnicode(uint32_t code, uint8_t isPressed); 207 | 208 | /// @summary: record key event as scancode 209 | /// @param code: scancode code 210 | /// @param isPressed : True if a key press event 211 | bool keyScancode(uint32_t code, uint8_t isPressed); 212 | 213 | /// @summary: end of scenario 214 | bool close(void); 215 | 216 | private: 217 | RDPP_DISALLOW_EVIL_CONSTRUCTORS(FileRecorder); 218 | 219 | bool write(const void *data, size_t len); 220 | 221 | FILE *_fp; 222 | char _buffer[64 *1024]; 223 | Timestamp _lastEventTimer; 224 | 225 | static const int _kFlushPerMilliSeconds = 5000; 226 | }; 227 | 228 | /// @summary: RSS File reader 229 | class FileReader 230 | { 231 | public: 232 | /// @param f: {file} file pointer use to read 233 | FileReader(const string &filename); 234 | ~FileReader(); 235 | 236 | bool header(RssHeader *hdr); 237 | 238 | /// @summary: read next event and return it 239 | bool nextEvent(Event *e, Buffer *eventData); 240 | 241 | private: 242 | RDPP_DISALLOW_EVIL_CONSTRUCTORS(FileReader); 243 | 244 | bool read(void *buf, size_t len); 245 | FILE *_fp; 246 | }; 247 | 248 | } // namespace rdpp 249 | 250 | #endif // _RDPP_CORE_RSS_H_ 251 | -------------------------------------------------------------------------------- /librdpp/core/scancode.h: -------------------------------------------------------------------------------- 1 | #ifndef _RDPP_CORE_SCANCODE_H_ 2 | #define _RDPP_CORE_SCANCODE_H_ 3 | 4 | #include 5 | 6 | namespace rdpp { 7 | 8 | /// @summary: try to convert native code to char code 9 | /// @return: char 10 | static char scancodeToChar(uint32_t code) 11 | { 12 | switch (code) { 13 | case 0x10: return 'q'; 14 | case 0x11: return 'w'; 15 | case 0x12: return 'e'; 16 | case 0x13: return 'r'; 17 | case 0x14: return 't'; 18 | case 0x15: return 'y'; 19 | case 0x16: return 'u'; 20 | case 0x17: return 'i'; 21 | case 0x18: return 'o'; 22 | case 0x19: return 'p'; 23 | case 0x1e: return 'a'; 24 | case 0x1f: return 's'; 25 | case 0x20: return 'd'; 26 | case 0x21: return 'f'; 27 | case 0x22: return 'g'; 28 | case 0x23: return 'h'; 29 | case 0x24: return 'j'; 30 | case 0x25: return 'k'; 31 | case 0x26: return 'l'; 32 | case 0x2c: return 'z'; 33 | case 0x2d: return 'x'; 34 | case 0x2e: return 'c'; 35 | case 0x2f: return 'v'; 36 | case 0x30: return 'b'; 37 | case 0x31: return 'n'; 38 | case 0x32: return 'm'; 39 | } 40 | 41 | RDPP_LOG("SCANCODE", INFO) << "unknown scancode " << (void *)code; 42 | return '\0'; 43 | } 44 | } // namespace rdpp 45 | 46 | #endif // _RDPP_CORE_SCANCODE_H_ 47 | -------------------------------------------------------------------------------- /librdpp/core/string_util.h: -------------------------------------------------------------------------------- 1 | #ifndef _RDPP_CORE_STRING_UTIL_H_ 2 | #define _RDPP_CORE_STRING_UTIL_H_ 3 | 4 | #include 5 | #include 6 | 7 | namespace rdpp { 8 | 9 | class StringUtil 10 | { 11 | public: 12 | static const int kMaxStringLen = 64 * 1024; 13 | 14 | /// @brief 格式化字符串 15 | static string format(const char *format, ...) 16 | { 17 | va_list ap; 18 | va_start(ap, format); 19 | string str; 20 | 21 | char *buf = (char *)malloc(kMaxStringLen); 22 | if (buf) { 23 | vsnprintf(buf, kMaxStringLen, format, ap); 24 | str = buf; 25 | free(buf); 26 | va_end(ap); 27 | } 28 | return str; 29 | } 30 | 31 | /// @brief 转换成int类型 32 | static int stoi(const string &str) 33 | { 34 | return (0 == str.length()) ? 0 : atoi(str.c_str()); 35 | } 36 | 37 | /// @brief 转换成unsigned int 38 | static unsigned int stoui(const string &str) 39 | { 40 | return (0 == str.length()) ? 0 : static_cast(atoi(str.c_str())); 41 | } 42 | 43 | /// @brief 转换成int64类型 44 | static int64_t stoi64(const std::string &str) 45 | { 46 | int64_t v = 0; 47 | #ifdef WIN32 48 | sscanf(str.c_str(), "%I64d", &v); 49 | #else 50 | sscanf(str.c_str(), "%lld", &v); 51 | #endif 52 | return v; 53 | } 54 | 55 | /// @brief转换成uint64类型 56 | static int64_t stoui64(const std::string &str) 57 | { 58 | int64_t v = 0; 59 | #ifdef WIN32 60 | sscanf(str.c_str(), "%I64u", &v); 61 | #else 62 | sscanf(str.c_str(), "%llu", &v); 63 | #endif 64 | return v; 65 | } 66 | 67 | /// @brief 转换成long 68 | static long stol(const string &str) 69 | { 70 | return (0 == str.length()) ? 0L : atol(str.c_str()); 71 | } 72 | 73 | /// @brief 转换成float 74 | static float stof(const string &str) 75 | { 76 | return (0 == str.length()) ? 0.0f : static_cast(atof(str.c_str())); 77 | } 78 | 79 | /// @brief 转换成double 80 | static double stod(const string &str) 81 | { 82 | return (0 == str.length()) ? 0.0 : atof(str.c_str()); 83 | } 84 | 85 | /// @brief 转换成bool 86 | static bool stob(const string &str) 87 | { 88 | return (0 == str.length() || str == "0" || str == "false" || str == "FALSE") ? false : true; 89 | } 90 | 91 | /// @brief 将int类型数据转成字符串 92 | static string toString(const int val) 93 | { 94 | char buf[32] = {0}; 95 | snprintf(buf, sizeof(buf), "%d", val); 96 | return buf; 97 | } 98 | 99 | /// @brief 将unsigned int类型数据转成字符串 100 | static string toString(const unsigned int val) 101 | { 102 | char buf[32] = {0}; 103 | snprintf(buf, sizeof(buf), "%u", val); 104 | return buf; 105 | } 106 | 107 | /// @brief 将long类型数据转成字符串 108 | static string toString(const long val) 109 | { 110 | char buf[32] = {0}; 111 | snprintf(buf, sizeof(buf), "%ld", val); 112 | return buf; 113 | } 114 | 115 | /// @brief 将long long类型数据转成字符串 116 | static string toString(const long long val) 117 | { 118 | char buf[32] = {0}; 119 | snprintf(buf, sizeof(buf), "%lld", val); 120 | return buf; 121 | } 122 | 123 | /// @brief 将double类型数据转成字符串 124 | static string toString(const double val) 125 | { 126 | char buf[32] = {0}; 127 | snprintf(buf, sizeof(buf), "%f", val); 128 | return buf; 129 | } 130 | 131 | /// @brief 将bool类型数据转成字符串 132 | static string toString(const bool val) 133 | { 134 | return val ? "1" : "0"; 135 | } 136 | 137 | /// @brief 转成大写字母 138 | static string upper(const string &str) 139 | { 140 | string s(str); 141 | for (string::size_type i = 0; i < s.length(); ++i) 142 | if (s[i] >= 'a' && str[i] <= 'z') { 143 | s[i] -= 0x20; 144 | } 145 | return s; 146 | } 147 | 148 | /// @brief 移除左侧的空格、换行符和制表符 149 | static string trimLeft(const string &str) 150 | { 151 | string::size_type index = str.find_first_not_of("\n\r\t"); 152 | if (index != string::npos) { 153 | return str.substr(index); 154 | } 155 | return str; 156 | } 157 | 158 | /// @brief 移除右侧的空格、换行符和制表符 159 | static string trimRight(const string &str) 160 | { 161 | string::size_type index = str.find_last_not_of("\n\r\t"); 162 | if (index != string::npos) { 163 | return str.substr(0, index + 1); 164 | } 165 | return str; 166 | } 167 | 168 | /// @brief 移除左右两侧的空格、换行符和制表符 169 | static string trim(const string &str) 170 | { 171 | return trimRight(trimLeft(str)); 172 | } 173 | 174 | /// @brief 反转字符串 175 | static string reverse(const string &str) 176 | { 177 | string result; 178 | for (int i = (int)str.size() - 1; i >= 0; --i) 179 | result.append(1, str[i]); 180 | return result; 181 | } 182 | }; 183 | 184 | } // namespace rdpp 185 | 186 | #endif // _RDPP_CORE_STRING_UTIL_H_ -------------------------------------------------------------------------------- /librdpp/core/timestamp.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/librdpp/core/timestamp.cpp -------------------------------------------------------------------------------- /librdpp/core/timestamp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 时间戳,精确到1毫妙,格式:20131001 08:30:00.000 3 | */ 4 | 5 | #ifndef _RDPP_CORE_TIMESTAMP_H_ 6 | #define _RDPP_CORE_TIMESTAMP_H_ 7 | 8 | #include 9 | 10 | namespace rdpp { 11 | 12 | class Timestamp 13 | { 14 | public: 15 | Timestamp() 16 | : _msTimestamp(0) 17 | {} 18 | Timestamp(int64_t msTimestamp) 19 | : _msTimestamp(msTimestamp) 20 | {} 21 | Timestamp(const Timestamp &ts) 22 | : _msTimestamp(ts._msTimestamp) 23 | {} 24 | 25 | string toFormatString(); 26 | 27 | uint64_t timestamp() const { return _msTimestamp; } 28 | 29 | bool valid() const { return _msTimestamp > 0; } 30 | 31 | 32 | static Timestamp now(); 33 | static Timestamp invalid() { return Timestamp(); } 34 | 35 | static const int kMilliSecondsPerSecond = 1000; 36 | 37 | private: 38 | uint64_t _msTimestamp; 39 | }; 40 | 41 | } // namespace rdpp 42 | 43 | #endif // _RDPP_CORE_TIMESTAMP_H_ 44 | -------------------------------------------------------------------------------- /librdpp/core/unicode/README.md: -------------------------------------------------------------------------------- 1 | Portable ASCII and Unicode string manipulation functions for C++. 2 | 3 | To use this library, simply include the following files in your project: 4 | - `utf.h` (main header file) 5 | - `utf.cpp` (main source file) 6 | - `unicode_data.h` (contains important data from the Unicode Consortium) 7 | 8 | At the time of this writing, the current Unicode standard is at version 7.0. 9 | To update this library for future versions of Unicode, follow the directions in 10 | `unicode_data/unicode_data_parser.py`. 11 | 12 | Copyright (C) 2014 Stephan Boyer 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /librdpp/core/unicode/unicode_data/unicode_data_parser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python -O 2 | 3 | # This script generates unicode_data.h, the header that contains information 4 | # such as which code points are considered whitespace, letters, numerals, 5 | # uppercase, etc. 6 | 7 | # It is unnecessary to run this script unless a new version of UnicodeData.txt 8 | # is published by the Unicode Consortium. At the time of this writing, the 9 | # current version is 7.0. 10 | 11 | # Upgrade procedure: 12 | # 1. Replace the UnicodeData.txt file in this directory with an updated version 13 | # from the Unicode Consortium. 14 | # 2. Run this script with no arguments from this directory. 15 | # It will overwrite unicode_data.h in the parent directory. 16 | 17 | CODE_POINT_NULL = "FFFFFFFF" 18 | 19 | CASE_NONE = "00" 20 | CASE_UPPER = "01" 21 | CASE_LOWER = "02" 22 | CASE_TITLE = "03" 23 | letters = [] # (code point, case, uppercase version, lowercase version, titlecase version) 24 | 25 | numbers = [] # code point 26 | 27 | whitespace = ["0009", "000A", "000B", "000C", "000D", "0085"] # code point 28 | 29 | newlines = ["000A", "000B", "000C", "000D", "0085"] # code point 30 | 31 | # get the lines of the file 32 | for line in open("UnicodeData.txt"): 33 | # make sure the line isn't empty 34 | if line.strip() == "": 35 | continue 36 | 37 | # split the line by semicolons 38 | parts = [part.strip() for part in line[:-1].strip().split(";")] 39 | 40 | # make sure the line has the correct number of parts 41 | if len(parts) != 15: 42 | print "error parsing line: "+line[:-1].strip() 43 | 44 | # letters 45 | if parts[12] == "": 46 | parts[12] = CODE_POINT_NULL 47 | if parts[13] == "": 48 | parts[13] = CODE_POINT_NULL 49 | if parts[14] == "": 50 | parts[14] = CODE_POINT_NULL 51 | if parts[2] == "Lu": 52 | letters.append((parts[0], CASE_UPPER, parts[12], parts[13], parts[14])) 53 | if parts[2] == "Ll": 54 | letters.append((parts[0], CASE_LOWER, parts[12], parts[13], parts[14])) 55 | if parts[2] == "Lt": 56 | letters.append((parts[0], CASE_TITLE, parts[12], parts[13], parts[14])) 57 | if parts[2] == "Lm": 58 | letters.append((parts[0], CASE_NONE, parts[12], parts[13], parts[14])) 59 | if parts[2] == "Lo": 60 | letters.append((parts[0], CASE_NONE, parts[12], parts[13], parts[14])) 61 | 62 | # numbers 63 | if parts[2] == "Nd": 64 | numbers.append(parts[0]) 65 | if parts[2] == "Nl": 66 | numbers.append(parts[0]) 67 | if parts[2] == "No": 68 | numbers.append(parts[0]) 69 | 70 | # whitespace 71 | if parts[2] == "Zs" or parts[2] == "Zl" or parts[2] == "Zp": 72 | whitespace.append(parts[0]) 73 | 74 | # line breaks 75 | if parts[2] == "Zl" or parts[2] == "Zp": 76 | newlines.append(parts[0]) 77 | 78 | # write the header file 79 | f = open("../unicode_data.h", "w") 80 | f.write("/*\n") 81 | f.write(" This header was compiled from unicode_data/unicode_data_parser.py.\n") 82 | f.write("*/\n") 83 | f.write("\n") 84 | f.write("#ifndef UNICODE_DATA_H\n") 85 | f.write("#define UNICODE_DATA_H\n") 86 | f.write("\n") 87 | f.write("#include \n") 88 | f.write("\n") 89 | f.write("#define CODE_POINT_NULL 0xFFFFFFFF\n") 90 | f.write("\n") 91 | f.write("#define CASE_NONE 0\n") 92 | f.write("#define CASE_UPPER 1\n") 93 | f.write("#define CASE_LOWER 2\n") 94 | f.write("#define CASE_TITLE 3\n") 95 | f.write("\n") 96 | f.write("struct letter {\n") 97 | f.write(" uint32_t code_point;\n") 98 | f.write(" uint8_t character_case;\n") 99 | f.write(" uint32_t upper_version;\n") 100 | f.write(" uint32_t lower_version;\n") 101 | f.write(" uint32_t title_version;\n") 102 | f.write("};\n") 103 | f.write("\n") 104 | f.write("#define NUM_LETTERS "+str(len(letters))+"\n"); 105 | f.write("\n") 106 | f.write("static letter letters[] = {\n") 107 | for letter in letters: 108 | f.write(" {0x"+letter[0]+", 0x"+letter[1]+", 0x"+letter[2]+", 0x"+letter[3]+", 0x"+letter[4]+"},\n") 109 | f.write("};\n") 110 | f.write("\n") 111 | f.write("#define NUM_NUMBERS "+str(len(numbers))+"\n") 112 | f.write("\n") 113 | f.write("static uint32_t numbers[] = {\n") 114 | for code_point in numbers: 115 | f.write(" 0x"+code_point+",\n") 116 | f.write("};\n") 117 | f.write("\n") 118 | f.write("#define NUM_WHITESPACE "+str(len(whitespace))+"\n") 119 | f.write("\n") 120 | f.write("static uint32_t whitespace[] = {\n") 121 | for code_point in whitespace: 122 | f.write(" 0x"+code_point+",\n") 123 | f.write("};\n") 124 | f.write("\n") 125 | f.write("#define NUM_NEWLINES "+str(len(newlines))+"\n") 126 | f.write("\n") 127 | f.write("static uint32_t newlines[] = {\n") 128 | for code_point in newlines: 129 | f.write(" 0x"+code_point+",\n") 130 | f.write("};\n") 131 | f.write("\n") 132 | f.write("#endif\n") 133 | f.close() 134 | -------------------------------------------------------------------------------- /librdpp/core/unicode/utf.h: -------------------------------------------------------------------------------- 1 | /* 2 | Portable ASCII and Unicode string manipulation functions for C++. 3 | */ 4 | 5 | #ifndef RDPP_CORE_UTF_H 6 | #define RDPP_CORE_UTF_H 7 | 8 | #include 9 | #include 10 | 11 | namespace utf { 12 | 13 | // exception for encoding errors 14 | class encode_error { 15 | public: 16 | // constructor 17 | encode_error(std::string error_message); 18 | 19 | // get the error message 20 | std::string get_message(); 21 | 22 | private: 23 | // the error message 24 | std::string message; 25 | }; 26 | 27 | // encoding types 28 | enum encoding_type { 29 | ENCODING_UNKNOWN, 30 | ENCODING_ASCII, 31 | ENCODING_UTF8, 32 | ENCODING_UTF16BE, 33 | ENCODING_UTF16LE, 34 | ENCODING_UTF32BE, 35 | ENCODING_UTF32LE, 36 | }; 37 | 38 | // detect the encoding for a string 39 | encoding_type detect_encoding(const std::string &input); 40 | 41 | // determine whether a string is valid in a particular encoding 42 | bool is_valid(const std::string &input, encoding_type encoding); 43 | 44 | // convert a string from one encoding to another 45 | std::string convert_encoding(const std::string &input, encoding_type input_encoding, encoding_type output_encoding, bool include_bom); 46 | 47 | static inline std::string ascii_to_unicode(const std::string &input) 48 | { 49 | return utf::convert_encoding(input, utf::ENCODING_ASCII, utf::ENCODING_UTF16LE, false); 50 | } 51 | 52 | static inline std::string unicode_to_ascii(const std::string &input) 53 | { 54 | return utf::convert_encoding(input, utf::ENCODING_UTF16LE, utf::ENCODING_ASCII, false); 55 | } 56 | 57 | // get the number of code points in a string 58 | size_t get_length(const std::string &input, encoding_type encoding); 59 | 60 | // return the number of bytes of the code point at pos, or 0 if the byte index does not refer to a valid code point 61 | size_t get_char_size(const std::string &input, size_t pos, encoding_type encoding); 62 | 63 | // get the code point at a particular byte index 64 | uint32_t get_char(const std::string &input, size_t pos, encoding_type encoding); 65 | 66 | // set the code point at a particular byte index 67 | void set_char(std::string &input, size_t pos, uint32_t code_point, encoding_type encoding); 68 | 69 | // add a code point to the end of a string 70 | void add_char(std::string &input, uint32_t code_point, encoding_type encoding); 71 | 72 | // determine whether a code point is a letter 73 | bool is_alpha(uint32_t code_point); 74 | 75 | // determine whether a code point is uppercase 76 | bool is_upper(uint32_t code_point); 77 | 78 | // determine whether a code point is lowercase 79 | bool is_lower(uint32_t code_point); 80 | 81 | // determine whether a code point is titlecase 82 | bool is_title(uint32_t code_point); 83 | 84 | // determine whether a code point is a number 85 | bool is_numeric(uint32_t code_point); 86 | 87 | // determine whether a code point is whitespace 88 | bool is_whitespace(uint32_t code_point); 89 | 90 | // determine whether a code point is a line separator 91 | bool is_newline(uint32_t code_point); 92 | 93 | // convert a code point to uppercase (return the input if no uppercase form exists) 94 | uint32_t to_upper(uint32_t code_point); 95 | 96 | // convert a code point to lowercase (return the input if no lowercase form exists) 97 | uint32_t to_lower(uint32_t code_point); 98 | 99 | // convert a code point to titlecase (return the input if no titlecase form exists) 100 | uint32_t to_title(uint32_t code_point); 101 | 102 | } 103 | 104 | #endif -------------------------------------------------------------------------------- /librdpp/librdpp.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {198A82F8-2469-45A9-A63D-7FB55F18A181} 15 | Win32Proj 16 | librdpp 17 | 18 | 19 | 20 | StaticLibrary 21 | true 22 | MultiByte 23 | 24 | 25 | StaticLibrary 26 | false 27 | true 28 | MultiByte 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | $(ProjectDir);$(SolutionDir);D:\DEV\include;D:\DEV\include\openssl\include;$(IncludePath) 42 | $(SolutionDir)bin\ 43 | librdppd 44 | D:\DEV\bin;$(LibraryPath) 45 | 46 | 47 | $(ProjectDir);$(SolutionDir);D:\DEV\include;D:\DEV\include\openssl\include;$(IncludePath) 48 | $(SolutionDir)bin\ 49 | librdpp 50 | D:\DEV\bin;$(LibraryPath) 51 | 52 | 53 | 54 | 55 | 56 | Level3 57 | Disabled 58 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 59 | 60 | 61 | Windows 62 | true 63 | 64 | 65 | 66 | 67 | Level3 68 | 69 | 70 | MaxSpeed 71 | true 72 | true 73 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 74 | 75 | 76 | Windows 77 | true 78 | true 79 | true 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /librdpp/librdpp.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;hpp;hxx;hm;inl;inc;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 | {ac665d30-1176-468a-9cb6-b083565fcb85} 18 | 19 | 20 | {ada4abba-85c9-4c47-b3be-eacd29b2e53d} 21 | 22 | 23 | {08b1ecc1-550c-4149-b2b4-e68c44d826f5} 24 | 25 | 26 | {e17842ea-a559-41ea-a53e-4e89564c962a} 27 | 28 | 29 | {1ce73404-838a-441f-8c2b-1cd1245e709d} 30 | 31 | 32 | {84879d55-8c5d-40da-8b42-1579852857f5} 33 | 34 | 35 | 36 | 37 | core 38 | 39 | 40 | core 41 | 42 | 43 | core 44 | 45 | 46 | rdp 47 | 48 | 49 | rdp 50 | 51 | 52 | rdp 53 | 54 | 55 | rdp 56 | 57 | 58 | rdp 59 | 60 | 61 | rdp\t125 62 | 63 | 64 | rdp\t125 65 | 66 | 67 | rdp\pdu 68 | 69 | 70 | rdp\pdu 71 | 72 | 73 | rdp\t125 74 | 75 | 76 | core 77 | 78 | 79 | core 80 | 81 | 82 | rdp\nla 83 | 84 | 85 | rdp\nla 86 | 87 | 88 | core\unicode 89 | 90 | 91 | core 92 | 93 | 94 | 95 | 96 | core 97 | 98 | 99 | core 100 | 101 | 102 | core 103 | 104 | 105 | core 106 | 107 | 108 | core 109 | 110 | 111 | core 112 | 113 | 114 | core 115 | 116 | 117 | core 118 | 119 | 120 | core 121 | 122 | 123 | rdp 124 | 125 | 126 | rdp 127 | 128 | 129 | rdp 130 | 131 | 132 | rdp 133 | 134 | 135 | rdp 136 | 137 | 138 | rdp\t125 139 | 140 | 141 | rdp\t125 142 | 143 | 144 | rdp\pdu 145 | 146 | 147 | rdp\pdu 148 | 149 | 150 | rdp\pdu 151 | 152 | 153 | rdp\pdu 154 | 155 | 156 | core 157 | 158 | 159 | rdp\t125 160 | 161 | 162 | core 163 | 164 | 165 | rdp\nla 166 | 167 | 168 | rdp\nla 169 | 170 | 171 | rdp\nla 172 | 173 | 174 | core\unicode 175 | 176 | 177 | core\unicode 178 | 179 | 180 | core 181 | 182 | 183 | core 184 | 185 | 186 | core 187 | 188 | 189 | -------------------------------------------------------------------------------- /librdpp/librdpp.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ..\..\..\..\..\..\DEV\bin 5 | WindowsLocalDebugger 6 | 7 | 8 | ..\..\..\..\..\..\DEV\bin 9 | WindowsLocalDebugger 10 | 11 | -------------------------------------------------------------------------------- /librdpp/rdp/lic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define TAG "LIC" 6 | 7 | namespace rdpp { 8 | 9 | /// @summary: A license packet 10 | struct LicPacket { 11 | uint8_t bMsgtype; 12 | uint8_t flag; 13 | uint16_t wMsgSize; // sizeof(this) 14 | 15 | LicPacket() : flag(PREAMBLE_VERSION_3_0) {} 16 | }; 17 | 18 | void createValidClientLicensingErrorMessage(Buffer *s) 19 | { 20 | LicensingErrorMessage message; 21 | LicPacket licPacket; 22 | 23 | message.dwErrorCode = STATUS_VALID_CLIENT; 24 | message.dwStateTransition = ST_NO_TRANSITION; 25 | message.write(s); 26 | 27 | licPacket.bMsgtype = MSG_TYPE_ERROR_ALERT; 28 | licPacket.wMsgSize = sizeof(licPacket) + s->length(); 29 | s->prepend(&licPacket, sizeof(licPacket)); 30 | } 31 | 32 | } // namespace rdpp 33 | 34 | using namespace rdpp; 35 | 36 | LicenseManager::LicenseManager(SecLayer *transport) 37 | : _transport(transport) 38 | { 39 | } 40 | 41 | bool LicenseManager::recv(Buffer *s) 42 | { 43 | LicPacket licPacket; 44 | s->retrieve(&licPacket, sizeof(licPacket)); 45 | 46 | // end of automata 47 | if (licPacket.bMsgtype == MSG_TYPE_ERROR_ALERT) { 48 | LicensingErrorMessage licensingMessage; 49 | licensingMessage.read(s); 50 | 51 | if (licensingMessage.dwErrorCode == STATUS_VALID_CLIENT && 52 | licensingMessage.dwStateTransition == ST_NO_TRANSITION) 53 | return true; 54 | } else if (licPacket.bMsgtype == MSG_TYPE_LICENSE_REQUEST) { 55 | ServerLicenseRequest licensingMessage; 56 | licensingMessage.read(s); 57 | sendClientNewLicenseRequest(licensingMessage); 58 | } else if (licPacket.bMsgtype == MSG_TYPE_PLATFORM_CHALLENGE) { 59 | ServerPlatformChallenge licensingMessage; 60 | licensingMessage.read(s); 61 | sendClientChallengeResponse(licensingMessage); 62 | return false; 63 | } else if (licPacket.bMsgtype == MSG_TYPE_NEW_LICENSE) { 64 | return true; // yes get a new license 65 | } 66 | 67 | RDPP_LOG(TAG, ERROR) << "Not a valid license packet"; 68 | return false; 69 | } 70 | 71 | void LicenseManager::sendLicensePacket(uint8_t type, Buffer *data) 72 | { 73 | LicPacket licPacket; 74 | 75 | licPacket.bMsgtype = type; 76 | licPacket.wMsgSize = sizeof(licPacket) + data->length(); 77 | data->prepend(&licPacket, sizeof(licPacket)); 78 | 79 | _transport->sendFlagged(SEC_LICENSE_PKT, data); 80 | } 81 | 82 | void LicenseManager::sendClientNewLicenseRequest(ServerLicenseRequest &licenseRequest) 83 | { 84 | Buffer messageS; 85 | ClientNewLicenseRequest message; 86 | ServerCertificate *serverCert; 87 | ServerCertificate tmpCert; 88 | uint8_t clientRandom[CLIENT_RANDOM_LENGTH]; 89 | uint8_t serverRandom[SERVER_RANDOM_LENGTH]; 90 | uint8_t preMasterSecret[PREMASTER_SECRET_LENGTH]; 91 | uint8_t masterSecret[MASTER_SECRET_LENGTH]; 92 | uint8_t sessionKeyBlob[SESSION_KEY_BLOB_LENGTH]; 93 | 94 | // get server information 95 | memcpy(serverRandom, licenseRequest.serverRandom.data(), SERVER_RANDOM_LENGTH); 96 | if (_transport->getGCCServerSettings().security.serverCertLen > 0) { 97 | serverCert = &_transport->getGCCServerSettings().security.serverCertificate; 98 | } else { 99 | Buffer s(licenseRequest.serverCertificate.blobData); 100 | tmpCert.read(&s); 101 | serverCert = &tmpCert; 102 | } 103 | 104 | // generate crypto values 105 | Rsa::random(clientRandom, 32); 106 | Rsa::random(preMasterSecret, 48); 107 | 108 | if (!security_master_secret(preMasterSecret, clientRandom, serverRandom, masterSecret) || 109 | !security_session_key_blob(masterSecret, clientRandom, serverRandom, sessionKeyBlob)) { 110 | return; 111 | } 112 | 113 | security_mac_salt_key(sessionKeyBlob, clientRandom, serverRandom, _macSaltKey); 114 | 115 | if (!security_licensing_encryption_key(sessionKeyBlob, clientRandom, serverRandom, _licensingEncryptionKey)) 116 | return; 117 | 118 | // format message 119 | Buffer modulus, exponent; 120 | serverCert->getPublicKey(modulus, exponent); 121 | 122 | Buffer encryptedPremasterSecret(modulus.length()); 123 | Rsa::public_encrypt(preMasterSecret,PREMASTER_SECRET_LENGTH, 124 | modulus.length(), modulus.data(), exponent.data(), 125 | (uint8_t *)encryptedPremasterSecret.beginWrite()); 126 | encryptedPremasterSecret.hasWritten(modulus.length()); 127 | 128 | message.clientRandom.assign(clientRandom, CLIENT_RANDOM_LENGTH); 129 | message.encryptedPreMasterSecret.append(encryptedPremasterSecret.data(), encryptedPremasterSecret.length()); 130 | message.ClientMachineName.append(_hostname.c_str(), _hostname.length()); 131 | message.ClientMachineName.append("\x00", 1); 132 | message.ClientUserName.append(_username.c_str(), _username.length()); 133 | message.ClientUserName.append("\x00", 1); 134 | 135 | message.write(&messageS); 136 | sendLicensePacket(MSG_TYPE_NEW_LICENSE_REQUEST, &messageS); 137 | } 138 | 139 | void LicenseManager::sendClientChallengeResponse(ServerPlatformChallenge &platformChallenge) 140 | { 141 | Rc4 rc4; 142 | Buffer buffer; 143 | uint8_t encryptedHardwareId[HWID_LENGTH]; 144 | Buffer &serverEncryptedChallenge(platformChallenge.encryptedPlatformChallenge.blobData); 145 | 146 | // decrypt server challenge 147 | // it should be TEST word in unicode format 148 | if (!rc4.setup(_licensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH)) 149 | return; 150 | buffer.resize(serverEncryptedChallenge.length()); 151 | if (!rc4.update(serverEncryptedChallenge.length(), serverEncryptedChallenge.data(), buffer.data())) 152 | return; 153 | 154 | if (memcmp(buffer.data(), "T\x00E\x00S\x00T\x00\x00\x00", buffer.length())) { // L"TEST" 155 | RDPP_LOG(TAG, ERROR) << "bad license server challenge"; 156 | return; 157 | } 158 | 159 | // generate hwid 160 | Buffer hwid; 161 | hwid.appendUInt32(2); 162 | hwid.append(_hostname); 163 | hwid.append(_username); 164 | hwid.append(16, '\0'); 165 | 166 | buffer.append(hwid.data(), HWID_LENGTH); 167 | 168 | if (!rc4.setup(_licensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH)) 169 | return; 170 | if (!rc4.update(HWID_LENGTH, hwid.data(), encryptedHardwareId)) 171 | return; 172 | 173 | ClientPLatformChallengeResponse message; 174 | message.encryptedPlatformChallengeResponse.append(serverEncryptedChallenge.data(), serverEncryptedChallenge.length()); 175 | message.encryptedHWID.append(encryptedHardwareId, HWID_LENGTH); 176 | 177 | if (!security_mac_data(_macSaltKey, buffer.data(), buffer.length(), message.MACData)) 178 | return; 179 | 180 | buffer.clear(); 181 | message.write(&buffer); 182 | sendLicensePacket(MSG_TYPE_PLATFORM_CHALLENGE_RESPONSE, &buffer); 183 | } 184 | -------------------------------------------------------------------------------- /librdpp/rdp/nla/cssp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @summary: Credential Security Support Provider (CredSSP) 3 | * @see: https://msdn.microsoft.com/en-us/library/cc226764.aspx 4 | * 5 | * 6 | * Connecttion Sequence: 7 | * 8 | * [client] [server] 9 | * 10 | * 1.send negotiate ------> 11 | * <------ 2.send challenge 12 | * 3.send authenticate ------> 13 | * <------ 4.send public key inc 14 | * 5.send credential ------> 15 | */ 16 | 17 | #ifndef _RDPP_RDP_NLA_CSSP_H_ 18 | #define _RDPP_RDP_NLA_CSSP_H_ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | namespace rdpp { 27 | 28 | /// @summary: main structure 29 | /// @see: https://msdn.microsoft.com/en-us/library/cc226780.aspx 30 | struct TSRequest { 31 | uint32_t version; 32 | Buffer negoToken; 33 | Buffer authInfo; 34 | Buffer pubKeyAuth; 35 | uint32_t errorCode; 36 | 37 | TSRequest() : version(2), errorCode(0) {} 38 | bool read(Buffer *s); 39 | bool write(Buffer *s); 40 | }; 41 | 42 | /// @summary: contain username and password 43 | /// @see: https://msdn.microsoft.com/en-us/library/cc226783.aspx 44 | /// 45 | /// TSPasswordCreds ::= SEQUENCE { 46 | /// domainName [0] OCTET STRING, 47 | /// userName [1] OCTET STRING, 48 | /// password [2] OCTET STRING 49 | /// } 50 | struct TSPasswordCreds { 51 | string domainName; 52 | string userName; 53 | string password; 54 | 55 | int write(Buffer *s); 56 | }; 57 | 58 | /// @summary: contain user information 59 | /// @see: https://msdn.microsoft.com/en-us/library/cc226782.aspx 60 | /// TSCredentials ::= SEQUENCE { 61 | /// credType [0] INTEGER, 62 | /// credentials [1] OCTET STRING 63 | /// } 64 | struct TSCredentials { 65 | uint32_t credType; 66 | TSPasswordCreds credentials; 67 | 68 | TSCredentials() : credType(1) {} 69 | int write(Buffer *s); 70 | }; 71 | 72 | /// @summary: Handle CSSP connection 73 | /// Proxy class for authentication 74 | class CSSP 75 | { 76 | public: 77 | typedef function OnRecvCallback; 78 | 79 | CSSP(TPKTLayer *tpkt, Layer *presentation, 80 | IAuthenticationProtocol *auth, 81 | RdpTransport *rdpTransport); 82 | 83 | void close(); 84 | 85 | /// @summary: Inherit from twisted.protocol class 86 | /// main event of received data 87 | void dataReceived(Buffer *data); 88 | 89 | /// @summary: start NLA authentication 90 | bool connectNla(void *ssl); 91 | 92 | /// @summary: second state in cssp automata 93 | void recvChallenge(Buffer *data); 94 | 95 | /// @summary: the server send the pubKeyBer + 1 96 | void recvPubKeyInc(Buffer *data); 97 | 98 | private: 99 | RDPP_DISALLOW_EVIL_CONSTRUCTORS(CSSP); 100 | 101 | bool getPublicKey(Buffer *pubkey); 102 | 103 | RdpTransport *_rdpTransport; 104 | OnRecvCallback _onRecvCallback; 105 | 106 | TPKTLayer *_tpkt; 107 | Layer *_presentation; 108 | IAuthenticationProtocol *_auth; 109 | void *_ssl; 110 | Buffer _pubKeyBer; 111 | }; 112 | 113 | } // namespace rdpp 114 | 115 | #endif // _RDPP_RDP_NLA_CSSP_H_ 116 | -------------------------------------------------------------------------------- /librdpp/rdp/nla/sspi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @summary: Security Service Provider Interface (Microsoft) 3 | */ 4 | #ifndef _RDP_RDP_NLA_SSPI_H_ 5 | #define _RDP_RDP_NLA_SSPI_H_ 6 | 7 | #include 8 | #include 9 | 10 | namespace rdpp { 11 | 12 | /// @summary: generic class for authentication Protocol(ex : ntlmv2, SPNEGO or kerberos) 13 | class IAuthenticationProtocol 14 | { 15 | public: 16 | /// @summary: Client first handshake message for authentication protocol 17 | virtual bool getNegotiateMessage(Buffer *data) = 0; 18 | 19 | // @summary: Client last handshake message 20 | virtual bool getAuthenticateMessage(Buffer *challengeRequest, Buffer *message) = 0; 21 | 22 | /// @summary: return encoded credentials accorded with authentication protocol nego 23 | /// @return: (domain, username, password) 24 | virtual void getEncodedCredentials(string &domain, string &usename, string &password) = 0; 25 | 26 | /// @summary: encrypt data with key exchange in Authentication protocol 27 | virtual bool GSS_WrapEx(Buffer *data) = 0; 28 | 29 | /// @summary: decrypt data with key exchange in Authentication protocol 30 | /// @param data: {str} 31 | virtual bool GSS_UnWrapEx(Buffer *data) = 0; 32 | }; 33 | 34 | } // namespace rdpp 35 | 36 | #endif // _RDP_RDP_NLA_SSPI_H_ 37 | -------------------------------------------------------------------------------- /librdpp/rdp/pdu/layer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement the main graphic layer 3 | * 4 | * In this layer are managed all mains bitmap update orders end user inputs 5 | */ 6 | 7 | #ifndef _RDPP_RDP_PDU_LAYER_H_ 8 | #define _RDPP_RDP_PDU_LAYER_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace rdpp { 18 | 19 | struct CapabilitySets; 20 | struct ClientCoreData; 21 | 22 | class SecLayer; 23 | 24 | /// @summary: Interface for PDU server automata listener 25 | class PduClientListener 26 | { 27 | public: 28 | /// @summary: Event call when PDU layer is ready to send events 29 | virtual void onReady() = 0; 30 | 31 | /// @summary: Event call when Windows session is ready 32 | virtual void onSessionReady() = 0; 33 | 34 | /// @summary: call when a bitmap data is received from update PDU 35 | virtual void onUpdate(std::vector &rectangles) = 0; 36 | 37 | //TODO virtual recvDstBltOrder(order) = 0; 38 | }; 39 | 40 | class PduServerListener 41 | { 42 | public: 43 | /// @summary: Event call when PDU layer is ready to send 44 | virtual void onReady() = 0; 45 | 46 | /// @summary: Event call when slow path input are available 47 | virtual void onSlowPathInput(uint16_t numEvents, Buffer *slowPathInputEvents) = 0; 48 | }; 49 | 50 | /// @summary: Global channel for MCS that handle session 51 | /// identification user, licensing management, and capabilities exchange 52 | class PDULayer : public Layer, public FastPathLayer 53 | { 54 | public: 55 | PDULayer(); 56 | 57 | /// @summary: Send a PDU data to transport layer 58 | /// @param pduMessage: PDU message 59 | void sendPDU(uint16_t pduType, Buffer *pduMessage); 60 | 61 | /// @summary: Send an PDUData to transport layer 62 | /// @param pduData: PDU data message 63 | void sendDataPDU(uint8_t pduType2, Buffer *pduData); 64 | 65 | uint32_t shareId() const { return _shareId; } 66 | 67 | ClientCapabilitySets &clientCapabilitySets() { return _clientCaps; } 68 | 69 | ServerCapabilitySets &serverCapabilitySets() { return _serverCaps; } 70 | 71 | SecLayer *transport(); 72 | 73 | protected: 74 | ServerCapabilitySets _serverCaps; 75 | ClientCapabilitySets _clientCaps; 76 | 77 | uint32_t _shareId; 78 | bool _clientFastPathSupported; 79 | 80 | private: 81 | RDPP_DISALLOW_EVIL_CONSTRUCTORS(PDULayer); 82 | 83 | virtual void send(Buffer *s) {} 84 | virtual void sendFastPath(uint16_t secFlag, Buffer *data) {} 85 | }; 86 | 87 | /// @summary: Client automata of PDU layer 88 | class ClientPDULayer : public PDULayer 89 | { 90 | public: 91 | /// @param listener : PDUClientListener 92 | ClientPDULayer(PduClientListener *listener); 93 | 94 | /// @summary: Connect message in client automata 95 | void connect(); 96 | 97 | /// @summary: Send PDU close packet and call close method on transport method 98 | void close(); 99 | 100 | /// @summary: Receive demand active PDU which contains 101 | /// Server capabilities.In this version of RDPY only 102 | /// Restricted group of capabilities are used. 103 | /// Send Confirm Active PDU 104 | /// Send Finalize PDU 105 | /// Wait Server Synchronize PDU 106 | /// @param s: Buffer 107 | void recvDemandActivePDU(Buffer *s); 108 | 109 | /// @summary: Receive from server 110 | /// Wait Control Cooperate PDU 111 | /// @param s: Buffer from transport layer 112 | void recvServerSynchronizePDU(Buffer *s); 113 | 114 | /// @summary: Receive control cooperate PDU from server 115 | /// Wait Control Granted PDU 116 | /// @param s: Buffer from transport layer 117 | void recvServerControlCooperatePDU(Buffer *s); 118 | 119 | /// @summary: Receive last control PDU the granted control PDU 120 | /// Wait Font map PDU 121 | /// @param s: Buffer from transport layer 122 | void recvServerControlGrantedPDU(Buffer *s); 123 | 124 | /// @summary: Last useless connection packet from server to client 125 | /// Wait any PDU 126 | /// @param s: Buffer from transport layer 127 | void recvServerFontMapPDU(Buffer *s); 128 | 129 | /// @summary: Main receive function after connection sequence 130 | /// @param s: Buffer from transport layer 131 | void recvPDU(Buffer *s); 132 | 133 | /// @summary: Implement IFastPathListener interface 134 | /// Fast path is needed by RDP 8.0 135 | /// @param fastPathS : {Buffer} that contain fast path data 136 | /// @param secFlag : {SecFlags} 137 | void recvFastPath(uint16_t secFlag, Buffer *fastPathS); 138 | 139 | /// @summary: read a data PDU object 140 | /// @param dataPDU: DataPDU object 141 | void readDataPDU(Buffer *s, uint16_t readLen); 142 | 143 | /// @summary: Read an update data PDU data 144 | /// dispatch update data 145 | /// @param: {UpdateDataPDU} object 146 | void readUpdateDataPDU(Buffer *s, uint16_t readLen); 147 | 148 | /// @summary: Send all client capabilities 149 | void sendConfirmActivePDU(); 150 | 151 | /// @summary: send a synchronize PDU from client to server 152 | void sendClientFinalizeSynchronizePDU(); 153 | 154 | /// @summary: send client input events 155 | /// @param pointerEvents: list of pointer events 156 | void sendInputEvents(uint16_t eventType, uint16_t numEvents, Buffer *slowPathInputEvents); 157 | 158 | private: 159 | RDPP_DISALLOW_EVIL_CONSTRUCTORS(ClientPDULayer); 160 | 161 | PduClientListener *_listener; 162 | ClientCoreData *_gccCore; 163 | }; 164 | 165 | /// @summary: Server automata of PDU layer 166 | class ServerPDULayer : public PDULayer 167 | { 168 | public: 169 | /// @param listener: PDUServerListener 170 | ServerPDULayer(PduServerListener *listener); 171 | 172 | /// @summary: Connect message for server automata 173 | void connect(); 174 | 175 | /// @summary: Receive confirm active PDU from client 176 | /// Capabilities exchange 177 | /// Wait Client Synchronize PDU 178 | /// @param s: Buffer 179 | void recvConfirmActivePDU(Buffer *s); 180 | 181 | /// @summary: Receive from client 182 | /// Wait Control Cooperate PDU 183 | /// @param s: Buffer from transport layer 184 | void recvClientSynchronizePDU(Buffer *s); 185 | 186 | /// @summary: Receive control cooperate PDU from client 187 | /// Wait Control Request PDU 188 | /// @param s: Buffer from transport layer 189 | void recvClientControlCooperatePDU(Buffer *s); 190 | 191 | /// @summary: Receive last control PDU the request control PDU from client 192 | /// Wait Font List PDU 193 | /// @param s: Buffer from transport layer 194 | void recvClientControlRequestPDU(Buffer *s); 195 | 196 | /// @summary: Last synchronize packet from client to server 197 | /// Send Server Finalize PDUs 198 | /// Wait any PDU 199 | /// @param s: Buffer from transport layer 200 | void recvClientFontListPDU(Buffer *s); 201 | 202 | /// @summary: Main receive function after connection sequence 203 | /// @param s: Buffer from transport layer 204 | void recvPDU(Buffer *s); 205 | 206 | /// @summary: read a data PDU object 207 | /// @param dataPDU: DataPDU object 208 | void readDataPDU(Buffer *s, uint16_t readLen); 209 | 210 | /// @summary: Implement IFastPathListener interface 211 | /// Fast path is needed by RDP 8.0 212 | /// @param fastPathS : Buffer that contain fast path data 213 | void recvFastPath(uint16_t secFlag, Buffer *fastPathS); 214 | 215 | /// @summary: Send server capabilities server automata PDU 216 | void sendDemandActivePDU(); 217 | 218 | /// @summary: Send last synchronize packet from server to client 219 | void sendServerFinalizeSynchronizePDU(); 220 | 221 | /// @summary: Send a PDU data to transport layer 222 | /// @param pduMessage: PDU message 223 | void sendPDU(uint16_t pduType, Buffer *pduMessage); 224 | 225 | /// @summary: Send bitmap update data 226 | /// @param bitmapDatas: List of data.BitmapData 227 | void sendBitmapUpdatePDU(std::vector &bitmapDatas); 228 | 229 | private: 230 | RDPP_DISALLOW_EVIL_CONSTRUCTORS(ServerPDULayer); 231 | 232 | PduServerListener *_listener; 233 | }; 234 | 235 | } // namespace rdpp 236 | 237 | #endif // _RDPP_RDP_PDU_LAYER_H_ 238 | -------------------------------------------------------------------------------- /librdpp/rdp/pdu/order.h: -------------------------------------------------------------------------------- 1 | /** 2 | * GDI order structure 3 | */ 4 | #ifndef _RDPP_RDP_PDU_ORDER_H_ 5 | #define _RDPP_RDP_PDU_ORDER_H_ 6 | 7 | #include 8 | 9 | namespace rdpp { 10 | 11 | #include 12 | 13 | /// @summary: Class order of drawing order 14 | /// @see: http://msdn.microsoft.com/en-us/library/cc241586.aspx 15 | enum ControlFlag { 16 | TS_STANDARD = 0x01, 17 | TS_SECONDARY = 0x02, 18 | TS_BOUNDS = 0x04, 19 | TS_TYPE_CHANGE = 0x08, 20 | TS_DELTA_COORDINATES = 0x10, 21 | TS_ZERO_BOUNDS_DELTAS = 0x20, 22 | TS_ZERO_FIELD_BYTE_BIT0 = 0x40, 23 | TS_ZERO_FIELD_BYTE_BIT1 = 0x80, 24 | }; 25 | 26 | /// @summary: Primary order type 27 | /// @see: http://msdn.microsoft.com/en-us/library/cc241586.aspx 28 | enum OrderType { 29 | TS_ENC_DSTBLT_ORDER = 0x00, 30 | TS_ENC_PATBLT_ORDER = 0x01, 31 | TS_ENC_SCRBLT_ORDER = 0x02, 32 | TS_ENC_DRAWNINEGRID_ORDER = 0x07, 33 | TS_ENC_MULTI_DRAWNINEGRID_ORDER = 0x08, 34 | TS_ENC_LINETO_ORDER = 0x09, 35 | TS_ENC_OPAQUERECT_ORDER = 0x0A, 36 | TS_ENC_SAVEBITMAP_ORDER = 0x0B, 37 | TS_ENC_MEMBLT_ORDER = 0x0D, 38 | TS_ENC_MEM3BLT_ORDER = 0x0E, 39 | TS_ENC_MULTIDSTBLT_ORDER = 0x0F, 40 | TS_ENC_MULTIPATBLT_ORDER = 0x10, 41 | TS_ENC_MULTISCRBLT_ORDER = 0x11, 42 | TS_ENC_MULTIOPAQUERECT_ORDER = 0x12, 43 | TS_ENC_FAST_INDEX_ORDER = 0x13, 44 | TS_ENC_POLYGON_SC_ORDER = 0x14, 45 | TS_ENC_POLYGON_CB_ORDER = 0x15, 46 | TS_ENC_POLYLINE_ORDER = 0x16, 47 | TS_ENC_FAST_GLYPH_ORDER = 0x18, 48 | TS_ENC_ELLIPSE_SC_ORDER = 0x19, 49 | TS_ENC_ELLIPSE_CB_ORDER = 0x1A, 50 | TS_ENC_INDEX_ORDER = 0x1B, 51 | }; 52 | 53 | /// @summary: used to describe a value in the range - 32768 to 32767 54 | /// @see: http://msdn.microsoft.com/en-us/library/cc241577.aspx 55 | struct CoordField 56 | { 57 | int8_t delta; 58 | int16_t coordinate; 59 | }; 60 | 61 | /// @summary: GDI Primary drawing order 62 | /// @see: http://msdn.microsoft.com/en-us/library/cc241586.aspx 63 | struct PrimaryDrawingOrder 64 | { 65 | uint8_t controlFlags; 66 | uint8_t orderType; 67 | }; 68 | 69 | /// @summary: The DstBlt Primary Drawing Order is used to paint 70 | /// a rectangle by using a destination - only raster operation. 71 | /// @see: http://msdn.microsoft.com/en-us/library/cc241587.aspx 72 | struct DstBltOrder 73 | { 74 | // only one field 75 | uint8_t fieldFlag; 76 | CoordField nLeftRect; 77 | CoordField nTopRect; 78 | CoordField nWidth; 79 | CoordField nHeight; 80 | CoordField bRop; 81 | }; 82 | 83 | #include 84 | 85 | } // namespace rdpp 86 | 87 | #endif // _RDPP_RDP_PDU_ORDER_H_ 88 | -------------------------------------------------------------------------------- /librdpp/rdp/t125/certificate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define TAG "CERTIFICATE" 5 | 6 | using namespace rdpp; 7 | 8 | static const uint8_t initial_signature[] = 9 | { 10 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 11 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 12 | 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 13 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 14 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 15 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 16 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 17 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01 18 | }; 19 | 20 | // Terminal Services Signing Keys. 21 | // Yes, Terminal Services Private Key is publicly available. 22 | // http ://msdn.microsoft.com/en-us/library/cc240776.aspx 23 | 24 | static const unsigned char tssk_modulus[] = 25 | { 26 | 0x3d, 0x3a, 0x5e, 0xbd, 0x72, 0x43, 0x3e, 0xc9, 27 | 0x4d, 0xbb, 0xc1, 0x1e, 0x4a, 0xba, 0x5f, 0xcb, 28 | 0x3e, 0x88, 0x20, 0x87, 0xef, 0xf5, 0xc1, 0xe2, 29 | 0xd7, 0xb7, 0x6b, 0x9a, 0xf2, 0x52, 0x45, 0x95, 30 | 0xce, 0x63, 0x65, 0x6b, 0x58, 0x3a, 0xfe, 0xef, 31 | 0x7c, 0xe7, 0xbf, 0xfe, 0x3d, 0xf6, 0x5c, 0x7d, 32 | 0x6c, 0x5e, 0x06, 0x09, 0x1a, 0xf5, 0x61, 0xbb, 33 | 0x20, 0x93, 0x09, 0x5f, 0x05, 0x6d, 0xea, 0x87 34 | }; 35 | 36 | static const unsigned char tssk_privateExponent[] = 37 | { 38 | 0x87, 0xa7, 0x19, 0x32, 0xda, 0x11, 0x87, 0x55, 39 | 0x58, 0x00, 0x16, 0x16, 0x25, 0x65, 0x68, 0xf8, 40 | 0x24, 0x3e, 0xe6, 0xfa, 0xe9, 0x67, 0x49, 0x94, 41 | 0xcf, 0x92, 0xcc, 0x33, 0x99, 0xe8, 0x08, 0x60, 42 | 0x17, 0x9a, 0x12, 0x9f, 0x24, 0xdd, 0xb1, 0x24, 43 | 0x99, 0xc7, 0x3a, 0xb8, 0x0a, 0x7b, 0x0d, 0xdd, 44 | 0x35, 0x07, 0x79, 0x17, 0x0b, 0x51, 0x9b, 0xb3, 45 | 0xc7, 0x10, 0x01, 0x13, 0xe7, 0x3f, 0xf3, 0x5f 46 | }; 47 | 48 | static const unsigned char tssk_exponent[] = 49 | { 50 | 0x5b, 0x7b, 0x88, 0xc0 51 | }; 52 | 53 | static const char* certificate_read_errors[] = 54 | { 55 | "Certificate tag", 56 | "TBSCertificate", 57 | "Explicit Contextual Tag [0]", 58 | "version", 59 | "CertificateSerialNumber", 60 | "AlgorithmIdentifier", 61 | "Issuer Name", 62 | "Validity", 63 | "Subject Name", 64 | "SubjectPublicKeyInfo Tag", 65 | "subjectPublicKeyInfo::AlgorithmIdentifier", 66 | "subjectPublicKeyInfo::subjectPublicKey", 67 | "RSAPublicKey Tag", 68 | "modulusLength", 69 | "zero padding", 70 | "modulusLength", 71 | "modulus", 72 | "publicExponent length", 73 | "publicExponent" 74 | }; 75 | 76 | 77 | /** 78 | * Read X.509 Certificate 79 | * @param certificate certificate module 80 | * @param cert X.509 certificate 81 | */ 82 | 83 | static bool certificate_read_x509_certificate(CertBlobPtr cert, Buffer &modulus, Buffer &exponent) 84 | { 85 | Buffer s; 86 | int length; 87 | uint8_t padding; 88 | uint32_t version; 89 | int modulus_length; 90 | int exponent_length; 91 | int error = 0; 92 | uint8_t exponent_tmp[4] = { 0,0,0,0 }; 93 | 94 | modulus.clear(); 95 | exponent.clear(); 96 | 97 | s.append(cert->abCert); 98 | 99 | if (!BER::readSequenceTag(&s, length)) /* Certificate (SEQUENCE) */ 100 | goto error1; 101 | 102 | error++; 103 | if (!BER::readSequenceTag(&s, length)) /* TBSCertificate (SEQUENCE) */ 104 | goto error1; 105 | 106 | error++; 107 | if (!BER::readContextualTag(&s, 0, length, true)) /* Explicit Contextual Tag [0] */ 108 | goto error1; 109 | 110 | error++; 111 | if (!BER::readInteger(&s, version)) /* version (INTEGER) */ 112 | goto error1; 113 | 114 | error++; 115 | version++; 116 | 117 | /* serialNumber */ 118 | uint32_t value; 119 | if (!BER::readInteger(&s, value)) /* CertificateSerialNumber (INTEGER) */ 120 | goto error1; 121 | 122 | error++; 123 | 124 | /* signature */ 125 | if (!BER::readSequenceTag(&s, length)) /* AlgorithmIdentifier (SEQUENCE) */ 126 | goto error1; 127 | s.retrieve(length); 128 | error++; 129 | 130 | /* issuer */ 131 | if (!BER::readSequenceTag(&s, length)) /* Name (SEQUENCE) */ 132 | goto error1; 133 | s.retrieve(length); 134 | error++; 135 | 136 | /* validity */ 137 | if (!BER::readSequenceTag(&s, length)) /* Validity (SEQUENCE) */ 138 | goto error1; 139 | s.retrieve(length); 140 | error++; 141 | 142 | /* subject */ 143 | if (!BER::readSequenceTag(&s, length)) /* Name (SEQUENCE) */ 144 | goto error1; 145 | s.retrieve(length); 146 | error++; 147 | 148 | /* subjectPublicKeyInfo */ 149 | if (!BER::readSequenceTag(&s, length)) /* SubjectPublicKeyInfo (SEQUENCE) */ 150 | goto error1; 151 | 152 | error++; 153 | 154 | /* subjectPublicKeyInfo::AlgorithmIdentifier */ 155 | if (!BER::readSequenceTag(&s, length)) /* AlgorithmIdentifier (SEQUENCE) */ 156 | goto error1; 157 | s.retrieve(length); 158 | error++; 159 | 160 | /* subjectPublicKeyInfo::subjectPublicKey */ 161 | if (!BER::readBitString(&s, length, padding)) /* BIT_STRING */ 162 | goto error1; 163 | 164 | error++; 165 | 166 | /* RSAPublicKey (SEQUENCE) */ 167 | if (!BER::readSequenceTag(&s, length)) /* SEQUENCE */ 168 | goto error1; 169 | 170 | error++; 171 | 172 | if (!BER::readIntegerLength(&s, modulus_length)) /* modulus (INTEGER) */ 173 | goto error1; 174 | 175 | error++; 176 | 177 | /* skip zero padding, if any */ 178 | do { 179 | if (s.length() < 1) 180 | goto error1; 181 | 182 | padding = s.peekUInt8(); 183 | 184 | if (padding == 0) { 185 | s.retrieve(1); 186 | modulus_length--; 187 | } 188 | } while (padding == 0); 189 | 190 | error++; 191 | 192 | if (((int)s.length()) < modulus_length) 193 | goto error1; 194 | 195 | s.retrieve(modulus, modulus_length); 196 | error++; 197 | 198 | if (!BER::readIntegerLength(&s, exponent_length)) /* publicExponent (INTEGER) */ 199 | goto error2; 200 | 201 | error++; 202 | 203 | if ((((int)s.length()) < exponent_length) || (exponent_length > 4)) 204 | goto error2; 205 | 206 | s.retrieve(&exponent_tmp[4 - exponent_length], exponent_length); 207 | exponent.assign(exponent_tmp, 4); 208 | 209 | Rsa::crypto_reverse(modulus.data(), modulus.length()); 210 | Rsa::crypto_reverse(exponent.data(), exponent.length()); 211 | return true; 212 | error2: 213 | modulus.clear(); 214 | exponent.clear(); 215 | error1: 216 | RDPP_LOG(TAG, ERROR) << "error reading when reading certificate: part=" << certificate_read_errors[error] << " error=" << error; 217 | return false; 218 | } 219 | 220 | bool ProprietaryServerCertificate::computeSignatureHash(uint8_t *signature) 221 | { 222 | memcpy(signature, initial_signature, sizeof(initial_signature)); 223 | 224 | Buffer s; 225 | s.appendUInt32(CERT_CHAIN_VERSION_1); 226 | s.appendUInt32(dwSigAlgId); 227 | s.appendUInt32(dwKeyAlgId); 228 | s.appendUInt16(wPublicKeyBlobType); 229 | s.appendUInt16(wPublicKeyBlobLen); 230 | PublicKeyBlob.write(&s); 231 | 232 | return Digest::digest("md5", (uint8_t *)s.data(), s.length(), signature, Digest::MD5_DIGEST_LENGTH); 233 | } 234 | 235 | bool ProprietaryServerCertificate::sign() 236 | { 237 | uint8_t encryptedSignature[Rsa::TSSK_KEY_LENGTH]; 238 | uint8_t signature[sizeof(initial_signature)]; 239 | 240 | memcpy(signature, initial_signature, sizeof(initial_signature)); 241 | 242 | if (!computeSignatureHash(signature)) { 243 | RDPP_LOG(TAG, ERROR) << "compute signature hash failed"; 244 | return false; 245 | } 246 | 247 | Rsa::private_encrypt(signature, sizeof(signature), Rsa::TSSK_KEY_LENGTH, 248 | tssk_modulus, tssk_privateExponent, encryptedSignature); 249 | 250 | wSignatureBlobLen = sizeof(encryptedSignature) + sizeof(padding); 251 | SignatureBlob.assign((char *)encryptedSignature, sizeof(encryptedSignature)); 252 | return true; 253 | } 254 | 255 | bool ProprietaryServerCertificate::verify() 256 | { 257 | uint8_t sig[Rsa::TSSK_KEY_LENGTH]; 258 | uint8_t signature[sizeof(initial_signature)]; 259 | 260 | if (wSignatureBlobLen != 72) { 261 | RDPP_LOG(TAG, ERROR) << "invalid signature length (got " << wSignatureBlobLen << ", expected 72)"; 262 | return false; 263 | } 264 | 265 | Rsa::public_decrypt(SignatureBlob.data(), SignatureBlob.length(), 266 | Rsa::TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent, sig); 267 | 268 | // Verify signature. 269 | memcpy(signature, initial_signature, sizeof(initial_signature)); 270 | if (!computeSignatureHash(signature)) { 271 | RDPP_LOG(TAG, ERROR) << "compute signature hash failed"; 272 | return false; 273 | } 274 | 275 | return (!memcmp(signature, sig, sizeof(signature))); 276 | } 277 | 278 | void X509CertificateChain::getPublicKey(Buffer &n, Buffer &e) 279 | { 280 | certificate_read_x509_certificate(CertBlobArray[CertBlobArray.size() - 1], n, e); 281 | } 282 | -------------------------------------------------------------------------------- /librdpp/rdp/t125/certificate.h: -------------------------------------------------------------------------------- 1 | #ifndef _RDPP_RDP_T125_CERTIFICATE_H_ 2 | #define _RDPP_RDP_T125_CERTIFICATE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace rdpp 11 | { 12 | #include 13 | 14 | #define SIGNATURE_ALG_RSA 0x00000001 15 | #define KEY_EXCHANGE_ALG_RSA 0x00000001 16 | 17 | #define BB_RSA_KEY_BLOB 6 18 | #define BB_RSA_SIGNATURE_BLOB 8 19 | 20 | /// @see: http://msdn.microsoft.com/en-us/library/cc240521.aspx 21 | enum CertificateType 22 | { 23 | CERT_CHAIN_VERSION_1 = 0x00000001, 24 | CERT_CHAIN_VERSION_2 = 0x00000002, 25 | CERT_CHAIN_VERSION_MASK = 0x7FFFFFFF, 26 | }; 27 | 28 | /// @see: http://msdn.microsoft.com/en-us/library/cc240520.aspx 29 | class RSAPublicKey 30 | { 31 | public: 32 | uint32_t magic; // magic is RSA1(0x31415352) 33 | uint32_t keylen; // modules.length() + sizeof(padding); 34 | uint32_t bitlen; 35 | uint32_t datalen; 36 | uint8_t pubExp[4]; 37 | Buffer modulus; // len = keylen - 8, MUST be ((bitlen / 8) + 8) bytes. 38 | char padding[8]; // 8 bytes of zero padding 39 | 40 | RSAPublicKey() 41 | : magic(0x31415352), keylen(0), bitlen(0), datalen(0) 42 | { 43 | memset(padding, 0, sizeof(padding)); 44 | } 45 | void read(Buffer *data) 46 | { 47 | magic = data->readUInt32(); 48 | keylen = data->readUInt32(); 49 | bitlen = data->readUInt32(); 50 | datalen = data->readUInt32(); 51 | data->retrieve(pubExp, 4); 52 | data->retrieve(modulus, keylen - sizeof(padding)); 53 | data->retrieve(padding, sizeof(padding)); 54 | } 55 | void write(Buffer *data) 56 | { 57 | assert(keylen == (modulus.length() + sizeof(padding))); 58 | assert(bitlen == ((keylen - 8) * 8)); 59 | assert(datalen == ((bitlen / 8) - 1)); 60 | 61 | data->appendUInt32(magic); 62 | data->appendUInt32(keylen); 63 | data->appendUInt32(bitlen); 64 | data->appendUInt32(datalen); 65 | data->append(pubExp, 4); 66 | data->append(modulus); 67 | data->append(padding, sizeof(padding)); 68 | } 69 | uint16_t size() 70 | { 71 | return sizeof(uint32_t) * 5 + keylen; 72 | } 73 | }; 74 | 75 | /// @summary: microsoft proprietary certificate 76 | /// @see: http://msdn.microsoft.com/en-us/library/cc240519.aspx 77 | class ProprietaryServerCertificate 78 | { 79 | public: 80 | uint32_t dwSigAlgId; // const 81 | uint32_t dwKeyAlgId; // const 82 | uint16_t wPublicKeyBlobType; // const 83 | uint16_t wPublicKeyBlobLen; 84 | RSAPublicKey PublicKeyBlob; 85 | uint16_t wSignatureBlobType; 86 | uint16_t wSignatureBlobLen; // = len(blob) + len(padding) 87 | Buffer SignatureBlob; 88 | char padding[8]; 89 | 90 | ProprietaryServerCertificate() 91 | : dwSigAlgId(SIGNATURE_ALG_RSA) 92 | , dwKeyAlgId(KEY_EXCHANGE_ALG_RSA) 93 | , wPublicKeyBlobType(BB_RSA_KEY_BLOB) 94 | , wSignatureBlobType(BB_RSA_SIGNATURE_BLOB) 95 | , wPublicKeyBlobLen(0) 96 | , wSignatureBlobLen(0) 97 | { 98 | memset(padding, 0, sizeof(padding)); 99 | } 100 | void getPublicKey(Buffer &n, Buffer &e) 101 | { 102 | RDPP_LOG("GCC", DEBUG) << "read RSA public key from proprietary certificate"; 103 | e.assign(PublicKeyBlob.pubExp, 4); 104 | n.assign(PublicKeyBlob.modulus); 105 | } 106 | void read(Buffer *data) 107 | { 108 | dwSigAlgId = data->readUInt32(); 109 | dwKeyAlgId = data->readUInt32(); 110 | wPublicKeyBlobType = data->readUInt16(); 111 | wPublicKeyBlobLen = data->readUInt16(); 112 | PublicKeyBlob.read(data); 113 | wSignatureBlobType = data->readUInt16(); 114 | wSignatureBlobLen = data->readUInt16(); 115 | data->retrieve(SignatureBlob, wSignatureBlobLen - sizeof(padding)); 116 | data->retrieve(padding, sizeof(padding)); 117 | } 118 | void write(Buffer *data) 119 | { 120 | assert(wSignatureBlobLen == (SignatureBlob.length() + sizeof(padding))); 121 | 122 | data->appendUInt32(dwSigAlgId); 123 | data->appendUInt32(dwKeyAlgId); 124 | data->appendUInt16(wPublicKeyBlobType); 125 | data->appendUInt16(wPublicKeyBlobLen); 126 | PublicKeyBlob.write(data); 127 | data->appendUInt16(wSignatureBlobType); 128 | data->appendUInt16(wSignatureBlobLen); 129 | data->append(SignatureBlob); 130 | data->append(padding, sizeof(padding)); 131 | } 132 | /// @summary: compute hash 133 | bool computeSignatureHash(uint8_t *signature); 134 | 135 | /// @summary: sign proprietary certificate 136 | /// @see: http://msdn.microsoft.com/en-us/library/cc240778.aspx 137 | bool sign(); 138 | /// @summary: verify certificate signature 139 | bool verify(); 140 | uint16_t size() 141 | { 142 | return 16 + SignatureBlob.length() + 8 + PublicKeyBlob.size(); 143 | } 144 | }; 145 | 146 | /// @summary: certificate blob, contain x509 data 147 | /// @see: http://msdn.microsoft.com/en-us/library/cc241911.aspx 148 | struct CertBlob { 149 | uint32_t cbCert; 150 | Buffer abCert; 151 | }; 152 | typedef shared_ptr CertBlobPtr; 153 | 154 | /// @summary: X509 certificate chain 155 | /// @see: http://msdn.microsoft.com/en-us/library/cc241910.aspx 156 | class X509CertificateChain 157 | { 158 | public: 159 | uint32_t NumCertBlobs; 160 | std::vector CertBlobArray; 161 | // padding; 8 + 4 * NumCertBlobs 162 | 163 | void getPublicKey(Buffer &n, Buffer &e); 164 | 165 | /// @todo: verify x509 signature 166 | bool verify() { return true; } 167 | 168 | void read(Buffer *data) 169 | { 170 | NumCertBlobs = data->readUInt32(); 171 | for (uint32_t i = 0; i < NumCertBlobs; ++i) { 172 | RDPP_LOG("GCC", DEBUG) << "X.509 Certificate #" << i + 1 << ", length:" << data->peekUInt32(); 173 | CertBlobPtr blob(new CertBlob); 174 | 175 | blob->cbCert = data->readUInt32(); 176 | data->retrieve(blob->abCert, blob->cbCert); 177 | CertBlobArray.push_back(blob); 178 | } 179 | // padding 180 | data->retrieve(8 + 4 * NumCertBlobs); 181 | } 182 | 183 | void write(Buffer *data) 184 | { 185 | assert(CertBlobArray.size() == NumCertBlobs); 186 | 187 | data->appendUInt32(NumCertBlobs); 188 | for (uint32_t i = 0; i < NumCertBlobs; ++i) { 189 | CertBlobPtr blob = CertBlobArray[i]; 190 | 191 | assert(blob->cbCert == blob->abCert.length()); 192 | data->appendUInt32(blob->cbCert); 193 | data->append(blob->abCert); 194 | } 195 | // padding 196 | data->append(8 + 4 * NumCertBlobs, '\0'); 197 | } 198 | uint16_t size() 199 | { 200 | uint16_t len = 4; 201 | for (uint32_t i = 0; i < NumCertBlobs; ++i) { 202 | len += (4 + CertBlobArray[i]->abCert.length()); 203 | } 204 | return len; 205 | } 206 | }; 207 | 208 | /// @summary: Server certificate structure 209 | /// @see: http://msdn.microsoft.com/en-us/library/cc240521.aspx 210 | class ServerCertificate 211 | { 212 | public: 213 | uint32_t dwVersion; 214 | ProprietaryServerCertificate proprietary; 215 | X509CertificateChain x509; 216 | 217 | ServerCertificate() : dwVersion(0) 218 | {} 219 | void read(Buffer *data) 220 | { 221 | dwVersion = data->readUInt32(); 222 | switch (dwVersion & CERT_CHAIN_VERSION_MASK) { 223 | case CERT_CHAIN_VERSION_1: proprietary.read(data); break; 224 | case CERT_CHAIN_VERSION_2: x509.read(data); break; 225 | } 226 | } 227 | void write(Buffer *data) 228 | { 229 | data->appendUInt32(dwVersion); 230 | switch (dwVersion & CERT_CHAIN_VERSION_MASK) { 231 | case CERT_CHAIN_VERSION_1: proprietary.write(data); break; 232 | case CERT_CHAIN_VERSION_2: x509.write(data); break; 233 | } 234 | } 235 | void getPublicKey(Buffer &n, Buffer &e) 236 | { 237 | switch (dwVersion & CERT_CHAIN_VERSION_MASK) { 238 | case CERT_CHAIN_VERSION_1: return proprietary.getPublicKey(n, e); 239 | case CERT_CHAIN_VERSION_2: return x509.getPublicKey(n, e); 240 | } 241 | } 242 | bool verify() 243 | { 244 | switch (dwVersion & CERT_CHAIN_VERSION_MASK) { 245 | case CERT_CHAIN_VERSION_1: return proprietary.verify(); 246 | case CERT_CHAIN_VERSION_2: return x509.verify(); 247 | } 248 | return false; 249 | } 250 | uint16_t size() 251 | { 252 | switch (dwVersion & CERT_CHAIN_VERSION_MASK) { 253 | case CERT_CHAIN_VERSION_1: 254 | return sizeof(dwVersion) + proprietary.size(); 255 | case CERT_CHAIN_VERSION_2: 256 | return sizeof(dwVersion) + x509.size(); 257 | } 258 | return 0; 259 | } 260 | }; 261 | 262 | #include 263 | 264 | } // namespace rdpp 265 | 266 | #endif // _RDPP_RDP_T125_CERTIFICATE_H_ 267 | -------------------------------------------------------------------------------- /librdpp/rdp/t125/gcc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define TAG "GCC" 6 | 7 | using namespace rdpp; 8 | 9 | static const uint8_t t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 }; 10 | static const string h221_cs_key("Duca"); 11 | static const string h221_sc_key("McDn"); 12 | 13 | ClientCoreData::ClientCoreData() 14 | { 15 | rdpVersion = RDP_VERSION_5_PLUS; 16 | desktopWidth = 1280; 17 | desktopHeight = 800; 18 | colorDepth = RNS_UD_COLOR_8BPP; 19 | sasSequence = RNS_UD_SAS_DEL; 20 | kbdLayout = KBD_LAYOUT_US; 21 | clientBuild = 3790; 22 | string _clientName(utf::ascii_to_unicode("rdpp")); 23 | memset(clientName, 0, sizeof(clientName)); 24 | memcpy(clientName, _clientName.c_str(), _clientName.length()); 25 | keyboardType = IBM_101_102_KEYS; 26 | keyboardSubType = 0; 27 | keyboardFnKeys = 12; 28 | 29 | memset(imeFileName, 0, sizeof(imeFileName)); 30 | postBeta2ColorDepth = RNS_UD_COLOR_8BPP; 31 | clientProductId = 1; 32 | serialNumber = 0; 33 | highColorDepth = HIGH_COLOR_24BPP; 34 | supportedColorDepths = RNS_UD_15BPP_SUPPORT | RNS_UD_16BPP_SUPPORT | RNS_UD_24BPP_SUPPORT | RNS_UD_32BPP_SUPPORT; 35 | earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU; 36 | 37 | memset(clientDigProductId, 0, sizeof(clientDigProductId)); 38 | 39 | connectionType = 0; 40 | pad1octet = 0; 41 | serverSelectedProtocol = 0; 42 | } 43 | 44 | bool ClientSettings::readConferenceCreateRequest(Buffer *s) 45 | { 46 | uint8_t choice; 47 | uint16_t length; 48 | uint8_t number; 49 | uint8_t selection; 50 | 51 | if (!PER::readChoice(s, choice) || 52 | !PER::readObjectIdentifier(s, t124_02_98_oid) || 53 | !PER::readLength(s, length) || 54 | !PER::readChoice(s, choice) || 55 | !PER::readSelection(s, selection) || 56 | !PER::readNumericString(s, 1) || 57 | !PER::readPadding(s, 1)) 58 | return false; 59 | 60 | if (!PER::readNumberOfSet(s, number)) 61 | return false; 62 | if (number != 1) { 63 | RDPP_LOG(TAG, ERROR) << "Invalid number of set in readConferenceCreateRequest"; 64 | return false; 65 | } 66 | if (!PER::readChoice(s, choice)) 67 | return false; 68 | if (choice != 0xc0) { 69 | RDPP_LOG(TAG, ERROR) << "Invalid choice in readConferenceCreateRequest"; 70 | return false; 71 | } 72 | if (!PER::readOctetStream(s, h221_cs_key, 4)) 73 | return false; 74 | if (!PER::readLength(s, length)) 75 | return false; 76 | 77 | DataBlock block; 78 | while (length > sizeof(block)) { 79 | s->retrieve(&block, sizeof(block)); 80 | 81 | switch (block.type) { 82 | case MSG_TYPE_CS_CORE: 83 | RDPP_LOG(TAG, TRACE) << "Read Settings: CS_CORE(" << block.length << ")"; 84 | memcpy(&core, s->data(), MIN((block.length - sizeof(block)), sizeof(core))); 85 | s->retrieve(block.length - sizeof(block)); 86 | break; 87 | case MSG_TYPE_CS_NET: 88 | RDPP_LOG(TAG, TRACE) << "Read Settings: CS_NET(" << block.length << ")"; 89 | network.read(s); 90 | break; 91 | case MSG_TYPE_CS_SECURITY: 92 | RDPP_LOG(TAG, TRACE) << "Read Settings: CS_SECURITY(" << block.length << ")"; 93 | s->retrieve(&security, sizeof(ClientSecurityData)); 94 | break; 95 | default: 96 | RDPP_LOG(TAG, TRACE) << "Read Settings: " << (void *)block.type << "(" << block.length << ")"; 97 | s->retrieve(block.length - sizeof(block)); 98 | break; 99 | } 100 | length -= block.length; 101 | } 102 | 103 | return true; 104 | } 105 | 106 | void ClientSettings::writeConferenceCreateRequest(Buffer *s) 107 | { 108 | Buffer settings; 109 | DataBlock::write(&settings, MSG_TYPE_CS_CORE, sizeof(ClientCoreData)); 110 | settings.append(&core, sizeof(ClientCoreData)); 111 | DataBlock::write(&settings, MSG_TYPE_CS_NET, network.size()); 112 | network.write(&settings); 113 | DataBlock::write(&settings, MSG_TYPE_CS_SECURITY, sizeof(ClientSecurityData)); 114 | settings.append(&security, sizeof(ClientSecurityData)); 115 | 116 | PER::writeChoice(s, 0); 117 | PER::writeObjectIdentifier(s, t124_02_98_oid); 118 | PER::writeLength(s, settings.length() + 14); 119 | PER::writeChoice(s, 0); 120 | PER::writeSelection(s, 0x80); 121 | PER::writeNumericString(s, "1", 1); 122 | PER::writePadding(s, 1); 123 | PER::writeNumberOfSet(s, 1); 124 | PER::writeChoice(s, 0xc0); 125 | PER::writeOctetStream(s, h221_cs_key, 4); 126 | PER::writeOctetStream(s, settings.retrieveAllAsString()); 127 | } 128 | 129 | bool ServerSettings::readConferenceCreateResponse(Buffer *s) 130 | { 131 | uint8_t choice; 132 | uint16_t length; 133 | uint16_t integer16; 134 | uint32_t integer32; 135 | uint8_t enumerated; 136 | uint8_t number; 137 | 138 | if (!PER::readChoice(s, choice) || 139 | !PER::readObjectIdentifier(s, t124_02_98_oid) || 140 | !PER::readLength(s, length) || 141 | !PER::readChoice(s, choice) || 142 | !PER::readInteger16(s, integer16, 1001) || 143 | !PER::readInteger(s, integer32) || 144 | !PER::readEnumerates(s, enumerated) || 145 | !PER::readNumberOfSet(s, number) || 146 | !PER::readChoice(s, choice)) 147 | return false; 148 | 149 | if (!PER::readOctetStream(s, h221_sc_key, 4)) { 150 | RDPP_LOG(TAG, ERROR) << "cannot read h221_sc_key"; 151 | return false; 152 | } 153 | 154 | PER::readLength(s, length); 155 | 156 | DataBlock block; 157 | while (length > sizeof(block)) { 158 | s->retrieve(&block, sizeof(block)); 159 | 160 | switch (block.type) { 161 | case MSG_TYPE_SC_CORE: 162 | s->retrieve(&core, block.length - sizeof(block)); 163 | break; 164 | case MSG_TYPE_SC_NET: 165 | RDPP_LOG(TAG, TRACE) << "Read Settings: CS_NET(" << block.length << ")"; 166 | network.read(s); 167 | break; 168 | case MSG_TYPE_SC_SECURITY: 169 | RDPP_LOG(TAG, TRACE) << "Read Settings: CS_SECURITY(" << block.length << ")"; 170 | security.read(s); 171 | break; 172 | default: 173 | RDPP_LOG(TAG, WARN) << "Read Settings: Unknown(type=" << block.type << ", length=" << block.length << ")"; 174 | s->retrieve(block.length - sizeof(block)); 175 | break; 176 | } 177 | length -= block.length; 178 | } 179 | return true; 180 | } 181 | 182 | void ServerSettings::writeConferenceCreateResponse(Buffer *s) 183 | { 184 | Buffer settings; 185 | 186 | DataBlock::write(&settings, MSG_TYPE_SC_CORE, sizeof(ServerCoreData)); 187 | settings.append(&core, sizeof(ServerCoreData)); 188 | DataBlock::write(&settings, MSG_TYPE_SC_NET, network.size()); 189 | network.write(&settings); 190 | DataBlock::write(&settings, MSG_TYPE_SC_SECURITY, security.size()); 191 | security.write(&settings); 192 | 193 | PER::writeChoice(s, 0); 194 | PER::writeObjectIdentifier(s, t124_02_98_oid); 195 | PER::writeLength(s, settings.length() + 14); 196 | PER::writeChoice(s, 0x14); 197 | PER::writeInteger16(s, 0x79F3, 1001); 198 | PER::writeInteger(s, 1); 199 | PER::writeEnumerates(s, 0); 200 | PER::writeNumberOfSet(s, 1); 201 | PER::writeChoice(s, 0xc0); 202 | PER::writeOctetStream(s, h221_sc_key, 4); 203 | PER::writeOctetStream(s, settings.retrieveAllAsString()); 204 | } 205 | -------------------------------------------------------------------------------- /librdpp/rdp/tpkt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define TAG "TPKT" 5 | 6 | using namespace rdpp; 7 | 8 | TPKTLayer::TPKTLayer(Layer *presentation, FastPathLayer *fastPathListener, 9 | RdpTransport *rdpTransport) 10 | : Layer(presentation) 11 | , FastPathLayer(fastPathListener) 12 | , _rdpTransport(rdpTransport) 13 | , _lastShortLength(0) 14 | , _secFlag(0) 15 | { 16 | } 17 | 18 | void TPKTLayer::connect() 19 | { 20 | RDPP_LOG(TAG, TRACE) << "TPKTLayer::connect"; 21 | 22 | // header is on two bytes 23 | expect(2, rdpp::bind(&TPKTLayer::readHeader, this, _1)); 24 | // no connection automata on this layer 25 | if (_presentation != NULL) 26 | _presentation->connect(); 27 | } 28 | 29 | void TPKTLayer::close() 30 | { 31 | _rdpTransport->transportClose(); 32 | } 33 | 34 | void TPKTLayer::dataReceived(Buffer *data) 35 | { 36 | while (true) { 37 | const size_t readableBytes = data->length(); 38 | 39 | if (readableBytes < _expectedLen) 40 | return; 41 | 42 | const size_t expectedLen = _expectedLen; 43 | Buffer packet; 44 | 45 | packet.append(data->data(), expectedLen); 46 | recv(&packet); 47 | data->retrieve(expectedLen); 48 | } 49 | } 50 | 51 | void TPKTLayer::readHeader(Buffer *data) 52 | { 53 | // first read packet version 54 | uint8_t version = data->readUInt8(); 55 | // classic packet 56 | if (FASTPATH_ACTION_X224 == version) { 57 | // padding 58 | data->readUInt8(); 59 | // read end header 60 | expect(2, rdpp::bind(&TPKTLayer::readExtendedHeader, this, _1)); 61 | } else { 62 | // is fast path packet 63 | _secFlag = (version >> 6) & 0x03; 64 | _lastShortLength = data->readUInt8(); 65 | if (_lastShortLength & 0x80) 66 | expect(1, rdpp::bind(&TPKTLayer::readExtendedFastPathHeader, this, _1)); // size is 1 byte more 67 | else 68 | expect(_lastShortLength - 2, rdpp::bind(&TPKTLayer::readFastPath, this, _1)); 69 | } 70 | } 71 | 72 | void TPKTLayer::readExtendedHeader(Buffer *data) 73 | { 74 | // next state is read data 75 | uint16_t size = data->readUInt16Be(); 76 | expect(size - 4, rdpp::bind(&TPKTLayer::readData, this, _1)); 77 | } 78 | 79 | void TPKTLayer::readExtendedFastPathHeader(Buffer *data) 80 | { 81 | uint8_t leftPart = data->readUInt8(); 82 | _lastShortLength &= ~0x80; 83 | uint16_t packetSize = (_lastShortLength << 8) + leftPart; 84 | // next state is fast patn data 85 | expect(packetSize - 3, rdpp::bind(&TPKTLayer::readFastPath, this, _1)); 86 | } 87 | 88 | void TPKTLayer::readFastPath(Buffer *data) 89 | { 90 | RDPP_LOG(TAG, TRACE) << "TPKTLayer::readFastPath()"; 91 | 92 | _fastPathListener->recvFastPath(_secFlag, data); 93 | expect(2, rdpp::bind(&TPKTLayer::readHeader, this, _1)); 94 | } 95 | 96 | void TPKTLayer::readData(Buffer *data) 97 | { 98 | RDPP_LOG(TAG, TRACE) << "TPKTLayer::readData()"; 99 | _presentation->recv(data); 100 | // next packet 101 | expect(2, rdpp::bind(&TPKTLayer::readHeader, this, _1)); 102 | } 103 | 104 | void TPKTLayer::send(Buffer *data) 105 | { 106 | RDPP_LOG(TAG, TRACE) << "TPKTLayer::send()"; 107 | 108 | data->prependUInt16Be(data->length() + 4); 109 | data->prependUInt8(0); 110 | data->prependUInt8(FASTPATH_ACTION_X224); 111 | _rdpTransport->transportSend(data); 112 | } 113 | 114 | void TPKTLayer::sendFastPath(uint16_t secFlag, Buffer *data) 115 | { 116 | data->prependUInt16Be((data->length() + 3) | 0x8000); 117 | data->prependUInt8(FASTPATH_ACTION_FASTPATH | ((secFlag & 0x03) << 6)); 118 | 119 | RDPP_LOG(TAG, TRACE) << "TPKTLayer::sendFastPath()"; 120 | _rdpTransport->transportSend(data); 121 | } 122 | 123 | void TPKTLayer::expect(size_t expectedLen, const Layer::OnRecvCallback &callback) 124 | { 125 | _expectedLen = expectedLen; 126 | setNextState(callback); 127 | } 128 | -------------------------------------------------------------------------------- /librdpp/rdp/tpkt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Transport packet layer implementation 3 | * Use to build correct size packet and handle slow path and fast path mode 4 | */ 5 | #ifndef _RDPP_RDP_TPKT_H_ 6 | #define _RDPP_RDP_TPKT_H_ 7 | 8 | #include 9 | #include 10 | 11 | namespace rdpp { 12 | 13 | /// @see: http://msdn.microsoft.com/en-us/library/cc240621.aspx 14 | /// @see: http://msdn.microsoft.com/en-us/library/cc240589.aspx 15 | enum FastPathAction { 16 | FASTPATH_ACTION_FASTPATH = 0x0, 17 | FASTPATH_ACTION_X224 = 0x3, 18 | }; 19 | 20 | /// @see: http://msdn.microsoft.com/en-us/library/cc240621.aspx 21 | enum SecFlags { 22 | // hihi 'secure' checksum but private key is public !!! 23 | FASTPATH_OUTPUT_SECURE_CHECKSUM = 0x1, 24 | FASTPATH_OUTPUT_ENCRYPTED = 0x2, 25 | }; 26 | 27 | /// @summary: TPKT layer in RDP protocol stack 28 | /// represent the Raw Layer in stack (first layer) 29 | /// This layer only handle size of packet and determine if is a fast path packet 30 | class TPKTLayer : public Layer, public FastPathLayer 31 | { 32 | public: 33 | TPKTLayer(Layer *presentation, FastPathLayer *fastPathListener, 34 | RdpTransport *rdpTransport); 35 | 36 | /// @summary: Call return transport layer 37 | virtual void connect(); 38 | 39 | virtual void close(); 40 | 41 | /// @summary: main event of received data 42 | void dataReceived(Buffer *data); 43 | 44 | /// @summary: Send encompassed data 45 | virtual void send(Buffer *data); 46 | 47 | /// @param fastPathS: {Type | Tuple} type transform to stream and send as fastpath 48 | virtual void sendFastPath(uint16_t secFlag, Buffer *data); 49 | 50 | private: 51 | RDPP_DISALLOW_EVIL_CONSTRUCTORS(TPKTLayer); 52 | 53 | virtual void recvFastPath(uint16_t secFlag, Buffer *data) {} 54 | 55 | /// @summary: Set next automata callback, 56 | /// But this callback will be only called when 57 | /// data have expectedLen 58 | /// @param expectedLen: in bytes length use to call next state 59 | /// @param callback : callback call when expected length bytes is received 60 | void expect(size_t expectedLen, const Layer::OnRecvCallback &callback); 61 | 62 | /// @summary: Read header of TPKT packet 63 | void readHeader(Buffer *data); 64 | 65 | /// @summary: Header may be on 4 bytes 66 | void readExtendedHeader(Buffer *data); 67 | 68 | /// @summary: Fast path header may be on 1 byte more 69 | void readExtendedFastPathHeader(Buffer *data); 70 | 71 | /// @summary: Fast path data 72 | void readFastPath(Buffer *data); 73 | 74 | /// @summary: Read classic TPKT packet, last state in tpkt automata 75 | void readData(Buffer *data); 76 | 77 | private: 78 | // len of next packet pass to next state function 79 | size_t _expectedLen; 80 | 81 | RdpTransport *_rdpTransport; 82 | 83 | uint8_t _lastShortLength; 84 | uint8_t _secFlag; 85 | }; 86 | 87 | } // namespace rdpp 88 | 89 | #endif // _RDPP_RDP_TPKT_H_ 90 | -------------------------------------------------------------------------------- /librdpp/rdp/x224.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement transport PDU layer 3 | * 4 | * This layer have main goal to negociate SSL transport 5 | * RDP basic security is supported only on client side 6 | */ 7 | 8 | #ifndef _RDPP_RDP_X224_H_ 9 | #define _RDPP_RDP_X224_H_ 10 | 11 | #include 12 | #include 13 | 14 | namespace rdpp { 15 | 16 | /// @summary: Message type 17 | enum X224MessageType 18 | { 19 | X224_TPDU_CONNECTION_REQUEST = 0xE0, 20 | X224_TPDU_CONNECTION_CONFIRM = 0xD0, 21 | X224_TPDU_DISCONNECT_REQUEST = 0x80, 22 | X224_TPDU_DATA = 0xF0, 23 | X224_TPDU_ERROR = 0x70, 24 | }; 25 | 26 | /// @summary: Negotiation header 27 | enum NegociationType 28 | { 29 | TYPE_RDP_NEG_REQ = 0x01, 30 | TYPE_RDP_NEG_RSP = 0x02, 31 | TYPE_RDP_NEG_FAILURE = 0x03, 32 | }; 33 | 34 | /// @summary: Protocols available for x224 layer 35 | /// @see: https://msdn.microsoft.com/en-us/library/cc240500.aspx 36 | enum Protocols 37 | { 38 | PROTOCOL_RDP = 0x00000000, 39 | PROTOCOL_SSL = 0x00000001, 40 | PROTOCOL_HYBRID = 0x00000002, 41 | PROTOCOL_RDSTLS = 0x00000004, 42 | PROTOCOL_HYBRID_EX = 0x00000008, 43 | }; 44 | 45 | /// @summary: Protocol negotiation failure code 46 | enum NegotiationFailureCode 47 | { 48 | SSL_REQUIRED_BY_SERVER = 0x00000001, 49 | SSL_NOT_ALLOWED_BY_SERVER = 0x00000002, 50 | SSL_CERT_NOT_ON_SERVER = 0x00000003, 51 | INCONSISTENT_FLAGS = 0x00000004, 52 | HYBRID_REQUIRED_BY_SERVER = 0x00000005, 53 | SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER = 0x00000006, 54 | }; 55 | 56 | /// @summary: x224 layer management 57 | class X224Layer : public Layer 58 | { 59 | public: 60 | X224Layer(Layer *presentation, RdpTransport *rdpTransport); 61 | 62 | /// @summary: Read data header from packet 63 | /// And pass to presentation layer 64 | void recvData(Buffer *s); 65 | 66 | /// @summary: Write message packet for TPDU layer 67 | /// Add TPDU header 68 | virtual void send(Buffer *s); 69 | 70 | uint32_t requestedProtocol() const { return _requestedProtocol; } 71 | uint32_t selectedProtocol() const { return _selectedProtocol; } 72 | void setRequestedPtotocol(uint32_t proto) { _requestedProtocol = proto; } 73 | 74 | protected: 75 | RDPP_DISALLOW_EVIL_CONSTRUCTORS(X224Layer); 76 | 77 | RdpTransport *_rdpTransport; 78 | uint32_t _requestedProtocol; 79 | uint32_t _selectedProtocol; 80 | }; 81 | 82 | class ClientX224Layer : public X224Layer 83 | { 84 | public: 85 | ClientX224Layer(Layer *presentation, RdpTransport *rdpTransport, NlaConnector *nlaConnector); 86 | 87 | /// @summary: Connection request for client send a connection request packet 88 | virtual void connect(); 89 | 90 | private: 91 | RDPP_DISALLOW_EVIL_CONSTRUCTORS(ClientX224Layer); 92 | 93 | /// @summary: Write connection request message 94 | /// Next state is recvConnectionConfirm 95 | /// @see: http://msdn.microsoft.com/en-us/library/cc240500.aspx 96 | void sendConnectionRequest(); 97 | 98 | /// @summary: Receive connection confirm message 99 | /// Next state is recvData 100 | /// Call connect on presentation layer if all is good 101 | /// @param data: Buffer that contain connection confirm 102 | /// @see: response -> http://msdn.microsoft.com/en-us/library/cc240506.aspx 103 | /// @see: failure ->http://msdn.microsoft.com/en-us/library/cc240507.aspx 104 | void recvConnectionConfirm(Buffer *s); 105 | 106 | private: 107 | NlaConnector *_nlaConnector; 108 | }; 109 | 110 | /// @summary: Server automata of X224 layer 111 | class ServerX224Layer : public X224Layer 112 | { 113 | public: 114 | /// @param presentation: {layer} upper layer, MCS layer in RDP case 115 | ServerX224Layer(Layer *presentation, RdpTransport *rdpTransport); 116 | 117 | // @summary: Connection request for server wait connection request packet from client 118 | void connect(); 119 | 120 | private: 121 | RDPP_DISALLOW_EVIL_CONSTRUCTORS(ServerX224Layer); 122 | 123 | /// @summary: Read connection confirm packet 124 | /// Next state is send connection confirm 125 | /// @see : http ://msdn.microsoft.com/en-us/library/cc240470.aspx 126 | void recvConnectionRequest(Buffer *s); 127 | 128 | /// @summary: Write connection confirm message 129 | /// Start TLS connection 130 | /// Next state is recvData 131 | /// @see : http://msdn.microsoft.com/en-us/library/cc240501.aspx 132 | void sendConnectionConfirm(); 133 | 134 | private: 135 | bool _forceSSL; 136 | }; 137 | 138 | } // namespace rdpp 139 | 140 | #endif // _RDPP_RDP_X224_H_ 141 | -------------------------------------------------------------------------------- /rdpmitm/proxy_acceptor.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/rdpmitm/proxy_acceptor.cpp -------------------------------------------------------------------------------- /rdpmitm/proxy_acceptor.h: -------------------------------------------------------------------------------- 1 | #ifndef _RDPP_MITM_PROXY_ACCEPTOR_H_ 2 | #define _RDPP_MITM_PROXY_ACCEPTOR_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace rdpp { 9 | 10 | class ProxyAcceptor : public ACE_Event_Handler 11 | { 12 | public: 13 | ProxyAcceptor(const string &ip, int port, 14 | const string &ouputDirectory, 15 | const string &privateKeyFilePath, 16 | const string &certificateFilePath, 17 | int clientSecurity, 18 | ACE_Reactor *reactor = NULL); 19 | 20 | virtual ~ProxyAcceptor(); 21 | 22 | int open(const ACE_INET_Addr &listenAddr); 23 | 24 | // Overridden methods from the ACE_Event_Handler 25 | virtual ACE_HANDLE get_handle() const { return _acceptor.get_handle(); } 26 | 27 | //Create a read handler for the new connection and register that 28 | // handler with the reactor. 29 | virtual int handle_input(ACE_HANDLE); 30 | 31 | // Close the listening socket. 32 | virtual int handle_close(ACE_HANDLE, ACE_Reactor_Mask); 33 | 34 | private: 35 | string _ip; 36 | int _port; 37 | ACE_Reactor *_reactor; 38 | ACE_SSL_SOCK_Acceptor _acceptor; 39 | string _ouputDirectory; 40 | string _privateKeyFilePath; 41 | string _certificateFilePath; 42 | int _clientSecurity; 43 | uint32_t _uniqueId; 44 | }; 45 | 46 | } // namespace rdpp 47 | 48 | #endif // _RDPP_MITM_PROXY_ACCEPTOR_H_ 49 | -------------------------------------------------------------------------------- /rdpmitm/proxy_client.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/rdpmitm/proxy_client.cpp -------------------------------------------------------------------------------- /rdpmitm/proxy_client.h: -------------------------------------------------------------------------------- 1 | #ifndef _RDPP_MITM_PROXY_CLIENT_H_ 2 | #define _RDPP_MITM_PROXY_CLIENT_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace rdpp { 10 | 11 | class ProxyServer; 12 | 13 | class ProxyClient : public ACE_Event_Handler, public RdpTransport, public RDPClientObserver 14 | { 15 | public: 16 | ProxyClient(ProxyServer *server, ACE_Reactor *reactor); 17 | virtual ~ProxyClient(); 18 | 19 | void setServer(ProxyServer *server) 20 | { _server = server; } 21 | 22 | RDPClientController *controller() 23 | { return _controller.get(); } 24 | 25 | int open(const ACE_INET_Addr &serverAddr); 26 | 27 | virtual ACE_HANDLE get_handle(void) const 28 | { return _stream.get_handle(); } 29 | 30 | virtual int handle_input(ACE_HANDLE fd); 31 | virtual int handle_close(ACE_HANDLE fd, ACE_Reactor_Mask mask); 32 | 33 | virtual void transportSend(Buffer *data); 34 | virtual void transportClose(); 35 | virtual bool startTls(); 36 | virtual bool isTlsSupport(); 37 | 38 | virtual void onReady(); 39 | virtual void onSessionReady(); 40 | virtual void onClose(); 41 | virtual void onUpdate(uint16_t destLeft, uint16_t destTop, uint16_t destRight, 42 | uint16_t destBottom, uint16_t width, uint16_t height, 43 | uint16_t bitsPerPixel, bool isCompress, const string &data); 44 | 45 | private: 46 | bool _sslEnabled; 47 | ACE_Reactor *_reactor; 48 | ACE_SSL_Context _context; 49 | ACE_SSL_SOCK_Stream _stream; 50 | Buffer _readBuffer; 51 | ProxyServer *_server; 52 | shared_ptr _controller; 53 | }; 54 | 55 | } // namespace rdpp 56 | 57 | #endif // _RDPP_MITM_PROXY_CLIENT_H_ 58 | -------------------------------------------------------------------------------- /rdpmitm/proxy_server.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/rdpmitm/proxy_server.cpp -------------------------------------------------------------------------------- /rdpmitm/proxy_server.h: -------------------------------------------------------------------------------- 1 | #ifndef _RDPP_MITM_PROXY_SERVER_H_ 2 | #define _RDPP_MITM_PROXY_SERVER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace rdpp { 11 | 12 | class ProxyClient; 13 | 14 | class ProxyServer : public ACE_Event_Handler, public RdpTransport, public RDPServerObserver 15 | { 16 | public: 17 | ProxyServer(const string &ip, int port, const string &rssFile, 18 | const string &privateKeyFile, const string &certificateFile, 19 | int clientSecurity, ACE_Reactor *reactor); 20 | ~ProxyServer(); 21 | 22 | bool open(); 23 | 24 | FileRecorder *rss() 25 | { return &_rss; } 26 | 27 | ACE_SSL_SOCK_Stream &peer() 28 | { return _stream; } 29 | 30 | RDPServerController *controller() 31 | { return _controller.get(); } 32 | 33 | void setClient(ProxyClient *client) 34 | { _client = client; } 35 | 36 | virtual ACE_HANDLE get_handle() const 37 | { return _stream.get_handle(); } 38 | 39 | virtual int handle_input(ACE_HANDLE fd); 40 | virtual int handle_close(ACE_HANDLE fd, ACE_Reactor_Mask mask); 41 | 42 | 43 | virtual void transportSend(Buffer *data); 44 | virtual void transportClose(); 45 | virtual bool startTls(); 46 | virtual bool isTlsSupport(); 47 | 48 | virtual void onReady(); 49 | virtual void onClose(); 50 | virtual void onKeyEventScancode(uint32_t code, bool isPressed, bool isExtended); 51 | virtual void onKeyEventUnicode(uint32_t code, bool isPressed); 52 | virtual void onPointerEvent(uint16_t x, uint16_t y, uint8_t button, bool isPressed); 53 | 54 | private: 55 | string _ip; 56 | int _port; 57 | bool _sslEnabled; 58 | ACE_Reactor *_reactor; 59 | ACE_SSL_Context _context; 60 | ACE_SSL_SOCK_Stream _stream; 61 | ProxyClient *_client; 62 | shared_ptr _controller; 63 | Buffer _readBuffer; 64 | ACE_INET_Addr _serverAddr; 65 | int _clientSecurityLevel; 66 | string _privateKeyFile; 67 | string _certificateFile; 68 | FileRecorder _rss; 69 | }; 70 | 71 | } // namespace rdpp 72 | 73 | #endif // _RDPP_MITM_PROXY_SERVER_H_ 74 | -------------------------------------------------------------------------------- /rdpmitm/rdp_audit.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | bool startRdpAuditLister(const string &id, const string &destIp, uint16_t destPort, uint16_t listenPort, 5 | const string &username, const string &password, const string &domain, 6 | ACE_Reactor *reactor); 7 | 8 | bool stopRdpAuditListener(const string &id); 9 | 10 | 11 | class RdpAuditListener 12 | { 13 | 14 | private: 15 | id; 16 | destIp; 17 | destPort; 18 | listenerPort; 19 | ProxyAcceptor; 20 | std::map 21 | }; 22 | 23 | 24 | bool mirrorRdpAuditSession 25 | 26 | class RdpAuditSession 27 | { 28 | 29 | clientIp; 30 | clientPort; 31 | 32 | RdpAuditListener *listener; 33 | 34 | sessionId; 35 | 36 | 37 | 38 | ProxyClient; 39 | ProxyServer; 40 | }; -------------------------------------------------------------------------------- /rdpmitm/rdpmitm.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/rdpp/3637a196733f7cd926b46ac9a25c6e7d39f374ea/rdpmitm/rdpmitm.cpp -------------------------------------------------------------------------------- /rdpmitm/rdpmitm.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {55BDC032-8A71-4B4E-95D8-5146236BF54A} 15 | Win32Proj 16 | rdpmitm 17 | 18 | 19 | 20 | Application 21 | true 22 | MultiByte 23 | 24 | 25 | Application 26 | false 27 | true 28 | MultiByte 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | true 42 | $(SolutionDir);$(SolutionDir)librdpp;D:\DEV\include;D:\DEV\include\openssl\include;$(IncludePath) 43 | D:\DEV\bin;$(SolutionDir)\bin;$(LibraryPath) 44 | $(SolutionDir)bin\ 45 | 46 | 47 | false 48 | $(SolutionDir);$(SolutionDir)librdpp;D:\DEV\include;D:\DEV\include\openssl\include;$(IncludePath) 49 | $(SolutionDir)bin\ 50 | D:\DEV\bin;$(SolutionDir)\bin;$(LibraryPath) 51 | 52 | 53 | 54 | 55 | 56 | Level3 57 | Disabled 58 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 59 | 60 | 61 | Console 62 | true 63 | ACEd.lib;libeay32.lib;ssleay32.lib;librdppd.lib;%(AdditionalDependencies) 64 | 65 | 66 | 67 | 68 | Level3 69 | 70 | 71 | MaxSpeed 72 | true 73 | true 74 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 75 | 76 | 77 | Console 78 | true 79 | true 80 | true 81 | ACE.lib;libeay32.lib;ssleay32.lib;librdpp.lib;%(AdditionalDependencies) 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | Document 114 | 115 | 116 | Document 117 | 118 | 119 | Document 120 | 121 | 122 | Document 123 | 124 | 125 | Document 126 | 127 | 128 | Document 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /rdpmitm/rdpmitm.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;hpp;hxx;hm;inl;inc;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 | {8d7be2df-9635-4a5c-bc5d-47a3b0a2ef84} 18 | 19 | 20 | 21 | 22 | ace_ssl 23 | 24 | 25 | ace_ssl 26 | 27 | 28 | ace_ssl 29 | 30 | 31 | ace_ssl 32 | 33 | 34 | ace_ssl 35 | 36 | 37 | ace_ssl 38 | 39 | 40 | ace_ssl 41 | 42 | 43 | 源文件 44 | 45 | 46 | 源文件 47 | 48 | 49 | 源文件 50 | 51 | 52 | 源文件 53 | 54 | 55 | 56 | 57 | ace_ssl 58 | 59 | 60 | ace_ssl 61 | 62 | 63 | ace_ssl 64 | 65 | 66 | ace_ssl 67 | 68 | 69 | ace_ssl 70 | 71 | 72 | ace_ssl 73 | 74 | 75 | ace_ssl 76 | 77 | 78 | ace_ssl 79 | 80 | 81 | ace_ssl 82 | 83 | 84 | 头文件 85 | 86 | 87 | 头文件 88 | 89 | 90 | 头文件 91 | 92 | 93 | 94 | 95 | ace_ssl 96 | 97 | 98 | ace_ssl 99 | 100 | 101 | ace_ssl 102 | 103 | 104 | ace_ssl 105 | 106 | 107 | ace_ssl 108 | 109 | 110 | ace_ssl 111 | 112 | 113 | -------------------------------------------------------------------------------- /rdpmitm/rdpmitm.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)bin 5 | WindowsLocalDebugger 6 | -l 1234 -k server.key -c server.crt -n -o d:\\test_rss 192.168.100.67 3389 7 | 8 | 9 | -l 1234 -k server.key -c server.crt -n -o d:\\test_rss 192.168.100.67 3389 10 | WindowsLocalDebugger 11 | 12 | -------------------------------------------------------------------------------- /rdpp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "librdpp", "librdpp\librdpp.vcxproj", "{198A82F8-2469-45A9-A63D-7FB55F18A181}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rdpmitm", "rdpmitm\rdpmitm.vcxproj", "{55BDC032-8A71-4B4E-95D8-5146236BF54A}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {198A82F8-2469-45A9-A63D-7FB55F18A181} = {198A82F8-2469-45A9-A63D-7FB55F18A181} 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {198A82F8-2469-45A9-A63D-7FB55F18A181}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {198A82F8-2469-45A9-A63D-7FB55F18A181}.Debug|Win32.Build.0 = Debug|Win32 19 | {198A82F8-2469-45A9-A63D-7FB55F18A181}.Release|Win32.ActiveCfg = Release|Win32 20 | {198A82F8-2469-45A9-A63D-7FB55F18A181}.Release|Win32.Build.0 = Release|Win32 21 | {55BDC032-8A71-4B4E-95D8-5146236BF54A}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {55BDC032-8A71-4B4E-95D8-5146236BF54A}.Debug|Win32.Build.0 = Debug|Win32 23 | {55BDC032-8A71-4B4E-95D8-5146236BF54A}.Release|Win32.ActiveCfg = Release|Win32 24 | {55BDC032-8A71-4B4E-95D8-5146236BF54A}.Release|Win32.Build.0 = Release|Win32 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /removejunk.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo ---------------------------------------------------- 3 | echo Press any key to delete all files with ending: 4 | echo *.aps *.idb *.ncp *.obj *.pch *.tmp *.sbr 5 | echo Visual c++/.Net junk 6 | echo ---------------------------------------------------- 7 | pause 8 | 9 | del /F /Q /S *.aps *.idb *.ncp *.obj *.pch *.sbr *.tmp *.pdb *.bsc *.ilk *.res *.ncb *.opt *.suo *.manifest *.dep *.sdf 10 | 11 | 12 | pause 13 | 14 | 15 | --------------------------------------------------------------------------------