This patch fixes a bug with mstsc connecting to a RDP security only FreeRDP server.
It seems like the mstsc shipped with Windows Seven considers packets after the nego_failure
packet as an error. So after trying to do TLS, depending on the timing, mstsc can print an
error message instead of retrying to connect with RDP security. With this patch, we
don't send the MCS disconnect message when the negociation has failed.
Before this patch, RDP security was (wrongly) the fallback when negociating a
security protocol between the client and the server. For example when a client
was claiming TLS-only when connecting to a FreeRDP based-server with RDP security only,
the result of the negociation was that the server started to do RDP security.
The expected behaviour is to send a nego failure packet with error code
SSL_NOT_ALLOWED_BY_SERVER. This patch fixes this.
We also try to handle all cases of failed negociation and return the corresponding
error code.
Commit 0357a38e31 modified the function
fastpath_send_update_pdu() to check if the desired update is possible
by checking the payload size against the computed maxLength and the
clients's advertised max request size.
If the check failed that commit added a workaround which simply
copied the payload to a slow path updade.
This workaround is totally flawed and causes protocol errors:
- the fast path update code is not checked and required data format
conversions are missing
- depending on the fast path update code rdp_send_data_pdu() would
have to be called with differend data pdu type values but the
workaround always uses DATA_PDU_TYPE_UPDATE
- the workaround does not check if the total size would exceed
the maximum possible size for a slow path update
The check if a fast path output is actually possible with the
passed parameters is basically a good idea.
However, if that check fails it would only indicate an error in
the server implementation who must not generate updates that
exceed the client's max request size.
Even though a slow-path conversion would be possible there is
much more involved than simply copying the payload stream.
In addition it is highly doubtful if there is a benefit at all.
Even the oldest rdesktop and windows ce clients do support fast
path and although some lack the multi-fragment update capability
we cannot really send larger updates using slow-path outputs.
For the reasons elucidated above, I have removed the workaround
but kept a modified version of the check if a fast-path output
is possible at all.
Commit 0357a38e31 has added some code
without any effect.
That commit added code to rdp_read_capability_sets() to check if
CAPSET_TYPE_MULTI_FRAGMENT_UPDATE was not received which caused
settings->MultifragMaxRequestSize to be set to 0.
- this was done in the wrong place because we do these kind
of checks in rdp_recv_confirm_active() by consulting the
variable settings->ReceivedCapabilities[]
- the code had no effect at all because MultifragMaxRequestSize gets
set to FASTPATH_FRAGMENT_SAFE_SIZE in rdp_recv_confirm_active()
if the CAPSET_TYPE_MULTI_FRAGMENT_UPDATE was not received.
Extend rdp_pointer with function SetPosition. Can then be used by
clients support setting pointer by server which might be used in
shadowing scenarios.
When a client disconnects from a server and its channel structures are removed, the global hash g_OpenHandles should not be destroyed. Only freed channels must be removed from the hash.
Skipping channels already loaded in freerdp_channels_client_load
This prevents channels already loaded in a context to be added a
second time to the channel list.
The input->FocusInEvent callback implementations (normal and fast-path) have
always sent the mouse position even if the pointer was outside of the freerdp
client area. In addition xfreerdp used the wrong pointer coordinates which
were relative to the root window instead of its own.
On focus-in the pointer position must only be sent if the pointer is
currently within the program's client area. However, the clients had no way
to pass that information to input->FocusInEvent which required an API change.
- removed mouse pointer x, y parameters from input interface's FocusInEvent
- clients are responsible to call input->MouseEvent on focus-in if necessary
- fixed xfreerdp and wfreerdp accordingly
Since commit a228952 FreeRDP generates corrupt licensing packets if the rdp
security layer is used and the peer did not indicate that it is capable of
processing encrypted licensing packets:
That commit changed rdp->sec_flags after the rdp stream was already initialized
with encryption enabled which placed the PDU payload at an incorrect offset.
Instead of directly modifying the rdp->sec_flags this patch temporarily
disables rdp->do_crypt during rdp stream initialization if the client has not
advertised support for encrypted licensing packets.
Some buggy server(s) send data for channels that weren't announced or
negotiated. When processing this data FreeRDP had a problem and always
used the last channel in the channels list even if it wasn't responsible
for the data. Depending on how the channel handled the data this could
lead to different kind of problems and also segmentation faults.
Now data for unknown channels is ignored and not processed further.
[MS-RDPBCGR] Section 5.3 describes the encryption level and method values for
standard RDP security.
Looking at the current usage of these values in the FreeRDP code gives me
reason to believe that there is a certain lack of understanding of how these
values should be handled.
The encryption level is only configured on the server side in the "Encryption
Level" setting found in the Remote Desktop Session Host Configuration RDP-Tcp
properties dialog and this value is never transferred from the client to the
server over the wire.
The possible options are "None", "Low", "Client Compatible", "High" and
"FIPS Compliant". The client receices this value in the Server Security Data
block (TS_UD_SC_SEC1), probably only for informational purposes and maybe to
give the client the possibility to verify if the server's decision for the
encryption method confirms to the server's encryption level.
The possible encryption methods are "NONE", "40BIT", "56BIT", "128BIT" and
"FIPS" and the RDP client advertises the ones it supports to the server in the
Client Security Data block (TS_UD_CS_SEC).
The server's configured encryption level value restricts the possible final
encryption method.
Something that I was not able to find in the documentation is the priority
level of the individual encryption methods based on which the server makes its
final method decision if there are several options.
My analysis with Windows Servers reveiled that the order is 128, 56, 40, FIPS.
The server only chooses FIPS if the level is "FIPS Comliant" or if it is the
only method advertised by the client.
Bottom line:
* FreeRDP's client side does not need to set settings->EncryptionLevel
(which was done quite frequently).
* FreeRDP's server side does not have to set the supported encryption methods
list in settings->EncryptionMethods
Changes in this commit:
Removed unnecessary/confusing changes of EncryptionLevel/Methods settings
Refactor settings->DisableEncryption
* This value actually means "Advanced RDP Encryption (NLA/TLS) is NOT used"
* The old name caused lots of confusion among developers
* Renamed it to "UseRdpSecurityLayer" (the compare logic stays untouched)
Any client's setting of settings->EncryptionMethods were annihilated
* All clients "want" to set all supported methods
* Some clients forgot 56bit because 56bit was not supported at the time the
code was written
* settings->EncryptionMethods was overwritten anyways in nego_connect()
* Removed all client side settings of settings->EncryptionMethods
The default is "None" (0)
* Changed nego_connect() to advertise all supported methods if
settings->EncryptionMethods is 0 (None)
* Added a commandline option /encryption-methods:comma separated list of the
values "40", "56", "128", "FIPS". E.g. /encryption-methods:56,128
* Print warning if server chooses non-advertised method
Verify received level and method in client's gcc_read_server_security_data
* Only accept valid/known encryption methods
* Verify encryption level/method combinations according to MS-RDPBCGR 5.3.2
Server implementations can now set settings->EncryptionLevel
* The default for settings->EncryptionLevel is 0 (None)
* nego_send_negotiation_response() changes it to ClientCompatible in that case
* default to ClientCompatible if the server implementation set an invalid level
Fix server's gcc_write_server_security_data
* Verify server encryption level value set by server implementations
* Choose rdp encryption method based on level and supported client methods
* Moved FIPS to the lowest priority (only used if other methods are possible)
Updated sample server
* Support RDP Security (RdpKeyFile was not set)
* Added commented sample code for setting the security level
When "detect" is used as gateway usage method (which is the default)
it is tried to by-pass gateway connection for local hosts.
The detection might take some time therefore print a message that people
are aware that a detection is tried.
Fixes#2171
Client side code always tells the server that it is capable of processing
encrypted licensing packages (SEC_LICENSE_ENCRYPT_SC) but didn't set
the recently added flag to indicate that.
Fixes#2196
rpc_send_enqueue_pdu returns -1 on error but the type of error isn't
distinguishable. Therefore make sure that the buffer gets always freed.
The only exception to this is when the pdu was already queued. Then the
dequeuing function should take care of freeing the buffer when
processing the pdu.
According to the Microsoft RDP specification, T.128 flow control PDUs
should be ignored when reading Share Control headers.
(http://msdn.microsoft.com/en-us/library/cc240576.aspx). This patch
checks if we got a flow control PDU (length = 0x8000) and advances the
stream to ignore the PDU.
The fOpRedundant field of the GlyphIndex primary drawing order
(MS-RDPEGDI, chapter 2.2.2.2.1.1.2.13) was neglected which resulted in some
severe text rendering errors.
* According to MS-RDPBCGR 2.2.7.1.5 the pointerCacheSize is optional
and its absence or a zero value indicates missing client support for
the New Pointer Update.
* Added and fixed some comments regarding the meaning of the KBDFLAGS_DOWN
keyboard flag and how it is currently used in the code.
"Fixed" the slow path keyboard input to generate the same keyboard flags
as the corresponding fast path code.
* Some arbitrary value was used for the ConnectPDULength in the GCC
Conference Create Response. According to MS-RDPBCGR 4.1.4 this value must
be ignored by the client so we encode a zero value instead.
"libfreerdp" consisted of multiple (small) single libraries. If the cmake
option MONOLITHIC was used only one library was build combining all of
the libfreerdp-* libraries.
The only exceptions to this are libfreerdp-server and libfreerdp-client these
are build as separate libraries.
This commit obsoltes non-monolithic builds and makes monolithic builds
the default. The cmake option MONOLITHIC is also removed.
* Zeroing xevent helped address some erratic behavior.
* valgrind complained about using xfBitmap uninitialized
during shutdown, traced it back to the initialization.
Bitmap_Prototype->size > sizeof(rdpBitmap).
* Early exit from recv_tpkt_pdu is necessary to address
a shutdown crash - the channelId value was being used
without being set in the disconnect case.
(freerdp_color_convert_drawing_order_color_to_gdi_color): Declare new
function.
* libfreerdp/codec/color.c:
(freerdp_color_convert_drawing_order_color_to_gdi_color): Implement.
(freerdp_image_convert_8bpp): Properly use the ARGB32/ABGR32/RGB32/BGR32
macros when converting 8bpp data to 32bpp.
(freerdp_image_convert_32bpp): Fix CLRCONV_ALPHA and CLRCONV_INVERT
processing for 32bpp destination.
(freerdp_mono_image_convert): Use ARGB32/ABGR32 when converting to 32bpp
and CLRCONV_ALPHA is set.
* libfreerdp/core/orders.c: Color data from drawing orders is
interpreted in big endian mode.
* libfreerdp/core/update.c (update_read_palette): Likewise.
* libfreerdp/gdi/16bpp.c (gdi_get_color_16bpp): GDI colors are stored as
RGB now.
* libfreerdp/gdi/32bpp.c (gdi_get_color_32bpp): Likewise.
* libfreerdp/gdi/gdi.c:
Use freerdp_color_convert_drawing_order_color_to_gdi_color() to convert
from drawing order color representation to GDI color representation
troughout.
* libfreerdp/gdi/graphics.c (gdi_Glyph_BeginDraw): Likewise.
(gdi_Glyph_EndDraw): Likewise.
transport_check_fds and transport_read_pdu had almost the same
functionality: reading and validating one pdu at a time.
Now transport_read_pdu reads one pdu from the transport layer and verifies
that the pdu data is valid - as before.
transport_read_pdu also ensures that the stream is sealed and
rewound when the pdu is received completely.
transport_check_fds just uses transport_read_pdu and does *not* do
the verification a second time based on the stream.
Besides the clean up this fixes the following problems:
* transport_read always read 4 bytes. Fast-path input synchronize pdus
are only 3 bytes long. In this case on byte got lost in the stream
buffer which lead to "de-synchronization" of server and
client.
* Size check in tpdu_read_connection_confirm - already read bytes
weren't taken into account.
* make sure fast-path packages are not fragmented if no
multifragment support was announced
* handle special server side case where the multifragment size
received from the client is smaller than one maximum fast-path
PDU size
This adds 2 arguments:
/tls-ciphers List of permitted openssl ciphers - see ciphers(1)
/tls-ciphers-netmon Use tls ciphers that netmon can parse
With KB2919355, client/server negotiate the use of
TLS cipher TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
which works fine except that netmon can't parse it.
By adding commandline /tls-ciphers-netmon, we restrict
the available ciphers to a list that netmon can
deal with. Also adds /tls-ciphers, which
accepts a string arg, for further customization.
winpr is now always build as single library.
The build option MONOLITHIC_BUILD doesn't influence this behavior anymore.
The only exception is winpr-makecert-tool which is still build as extra
library.
This obsoletes complex_libraries for winpr.
# By Marc-André Moreau (20) and others
# Via Mike McDonald (6) and others
* 'master' of git://github.com/awakecoding/FreeRDP: (26 commits)
libfreerdp-codec: fix C++ headers
libfreerdp-codec: fix ClearCodec short vbar cache hit
libfreerdp-codec: improve ClearCodec error checking
libfreerdp-codec: fix ClearCodec RLEX decoding
libfreerdp-codec: ClearCodec fix error codes and wrapping around of cursors
libfreerdp-codec: fix some ClearCodec flag checking
Fixed issue with last merge.
Added #ifdef WITH_OPENH264 ... #endif to appropriate places in the code.
libfreerdp-codec: handle long vbar length mismatch
channels/rdpgfx: add egfx command line options and settings
libfreerdp-codec: reduce number of variables
libfreerdp-codec: improve ClearCodec robustness
libfreerdp-codec: simplify ClearCodec code
Initial implementation of H.264 decoder for MS-RDPEGFX
libfreerdp-codec: improve ClearCodec subcodec xStart, yStart handling
libfreerdp-codec: improve ClearCodec subcodec support
libfreerdp-codec: improve ClearCodec error checking
libfreerdp-codec: more ClearCodec vBar caching
channels/rdpgfx: harden parsing code
libfreerdp-codec: add ClearCodec glyph cache
...
select() has the major drawback that it cannot handle file descriptor
that are bigger than 1024. This patch makes use of poll() instead of
select() when poll() support is available.
This patch introduce misc checks when receiving pointer updates. We check
that the cursor are in the bounds defined by the spec. We also check that
the announced mask sizes are what they should be.
This big patch allows to have non-blocking writes. To achieve
this, it slightly changes the way transport is handled. The misc transport
layers are handled with OpenSSL BIOs. In the chain we insert a
bufferedBIO that will bufferize write calls that couldn't be honored.
For an access with Tls security the BIO chain would look like this:
FreeRdp Code ===> SSL bio ===> buffered BIO ===> socket BIO
The buffered BIO will store bytes that couldn't be send because of
blocking write calls.
This patch also rework TSG so that it would look like this in the
case of SSL security with TSG:
(TSG in)
> SSL BIO => buffered BIO ==> socket BIO
/
FreeRdp => SSL BIO => TSG BIO
\
> SSL BIO => buffered BIO ==> socket BIO
(TSG out)
So from the FreeRDP point of view sending something is only BIO_writing
on the frontBio (last BIO on the left).
This patch changes the prototype for decode_base64 so that the encode / decode
method are consistant (encode(BYTE *) => char* and decode(char*) => BYTE*).
It also does some improvements with unrolling loops so that end conditions are
tested only at the end.
The patch also adds some unitary tests.
Before the patch base64_decode() made valgrind complain about uninitialized
bits, after valgrind is happy and very quiet.
# By Marc-André Moreau
# Via Benoit LeBlanc (1) and Marc-André Moreau (1)
* 'master' of https://github.com/mrthebunny/FreeRDP:
libfreerdp-core: fix potential crash on session redirection failure
This patch fixes an issue with hung clients connected to FreeRDP server:
- Removed the completely useless inner while loop which used the transport
receive buffer stream position as break contition: The transport receive
buffer stream is replaced after each iteration of this loop with a fresh
instance from a pool which has the position set to 0. Thus it was
technically impossible that this loop would ever be run twice.
- We must not always return if transport_read_nonblocking returns 0:
transport_read_nonblocking() is also called in transport_write() and
therefore it is possible that the stream position of the transport
receive buffer is already > 0 when entering transport_check_fds.
- fixed invalid stream position if extEncryptionMethods is not used
- enabled 56bit rdp security method
- fixed entropy reduction of the keys for 40 bit and 56 bit
- added rdp security incl. FIPS for fastpath output
- added FIPS encryption to fast path input
- fixed FIPS key generation in server mode
- fixed stream length correction in FIPS mode
- added rdp encryption for licensing packets (apparently some clients,
specifically cetsc, require the license packets received from the
server to be encrypted under certain RDP encryption levels)
- replace errnous virtual extended mouse event in focus in event
Malloc can fail so it will, this patch adds some check in some places
where malloc/strdup results were not checked.
This patch also contains a server side fix for RDP security (credit to nfedera).
The signature len was badly set in the GCC packet. And some other RDP security
oriented fixes are also there.