The file clipboard delegate needs a base URI to operate on for
systems that are not WIN32. Added that to the context and abort
conversion, if that is not set. (currently not fully implemented)
Since this function calls WLog_GetLogLevel anyway better only
export the API to allow internal checks to be modified in the
future without breaking API
It's sometime useful to create a stream aliasing a buffer on the stack, and
it's nice if we don't need some extra malloc for this.
Example use:
BYTE buffer[20];
wStream s;
Stream_StaticInit(&s, buffer, sizeof(buffer));
Stream_Write_UINT16(&s, 0xff01);
Stream_Free(&s, FALSE);
(we overwrite the password and pin arguments).
This implies changes in the argument parsing tests that now must pass a mutable argv
(copied from the statically declared test argvs).
Some other const inconsistency have been dealt with too.
When using pthread_once with destructors they are only called,
if each thread (including the main thread) is exited with pthread_exit.
Introducing winpr_exit as a wrapper for that purpose.
SCardAddReaderName isn't part of the SCard API.
Note: removing this also removes the possibility to redirect single
smartcard readers with /smartcard:READERNAME. However this features
wasn't implemented in a general way and will be re-added as part of
the smart card channel directly.
To be able to avoid password conversion if the password is already unicode
this change adds the sspi_SetAuthIdentityWithUnicodePassword() function
that is identical to sspi_SetAuthIdentity() except that the password is
used without further conversions in the Unicode identity.
FreeRDP aborts if OpenSSL operates in FIPS mode and +fipsmode is not
manually specified. Let's prevent the abortion and enable the necessary
options in that case automatically.
This option will ensure that NLA is disabled(since NTLM uses weak crypto algorithms), FIPS
encryption is enabled, and ensure fips mode is enabled for openssl.
Selectively override specific uses of MD5/RC4 with new API calls specifically tailored to override FIPS.
Add comments on why overriding the use of these algorithms under FIPS is acceptable for the locations where overrides happen.
Remove check of server proprietary certificate which was already being ignore to avoid use of MD5.
Initialize winpr openssl earlier to ensure fips mode is set before starting using any crypto algorithms.
Adds a callback that allows servers to compute NTLM hashes by themselves. The typical
use of this callback is to provide a function that gives precomputed hash values.
Sponsored by: Wheel Systems (http://www.wheelsystems.com)
This header file (currently) provides definitions of FILEDESCRIPTOR
structure and GetUserProfileDirectory() function. However, it does so
only when included on non-Windows platforms. The code which includes it
fails to build on Windows because the definitions are absent and it
causes weird compilation errors (like FILEDESCRIPTOR being treated as
the name of a function argument).
Inculde <shlobj.h> to get FILEDESCRIPTOR and <userenv.h> for the
GetUserProfileDirectory() function. (And hope that this will not
pull more Windows headers than we need in the files which include
<winpr/shell.h>.)
Another issue revealed during testing is that older Windows systems
cannot handle the reserved file names well. While Windows 8 and 10 are
fine (they silently abort the file transfer), using reserved names with
Windows 7 can flat out crash explorer.exe or result into weird error
messages like "fatal error: 0x00000000 ERROR_SUCCESS".
This is not required by MS-RDPECLIP specification, but we should try to
avoid this issue as not using reserved file names seems to be assumed
a common sense in Windows protocols.
The most convenient way to handle the issue would be on wClipboard level
so that WinPR's clients do not bother with it. We should prohibit the
reserved names from being used in FILEDESCRIPTOR, failing the conversion
if we see such a file.
POSIX subsystem (the only one at the moment) handles remote file names
in two places so move the Unicode conversion and the new validation
check into a separate function.
The reserved file name predicate is placed into <winpr/file.h> so that
it can be used in other places too. For example, other wClipboard local
file subsystems will need it. (It would be really nice to enforce this
check somewhere in the common code, so that the subsystems can't miss
it, but other places can miss some errors thus we're doing it here, as
early as possible.)
The predicate acts on separate file name components rather than full
file names because the backslash is a reserved character too. If we
process full file names this can result in phantom directory entry in
the remote file name. Not to say that handling ready-made components
spares us from splitting the full file name to extract them :)
The implementation is... a bit verbose, but that's fine by me. In the
absence of functions for case-insensitive wide string comparison and
the need to check for the [0-9] at the end of some file names this is
quite readable. Thanks to FAT and NTFS for being case-insensitive and
to MS-DOS for having reserved file names in the first place.
This is another bunch of callbacks which provide the file contents to
the clients. We jump through some extra hoops in order to have more
pleasant user experience.
Simple stuff goes first. The file offset (or position) is split into the
low and high parts because this is the format in which the clients
receive the request from the server. They can simply copy the values as
is into the struct without repackaging them (which we do instead in the
end to get a 64-bit off_t).
Another thing is that we try to minimize the number of lseek() calls and
to keep as few file descriptors open as possible. We cannot open all the
files at once as there could be thousands of them and we'll run out of
the allowed number of the fds. However, the server can (in theory)
request the file ranges randomly so we need to be prepared for that. One
way to do that would be to always open the file before reading and close
it immediately afterwards. A dead simple solution with an acceptable
performance, but... some file systems do not support seeking, such as
FTP directories mounted over FUSE. However, they handle sequential
reading just fine *and* the server requests the data sequentially most
of the time so we can exploit this.
Thus open the file only once, during the first range request and keep
it open until the server reads all the data. In order to know how much
data is left we keep an accurate account of all reads and maintain the
file offset ourselves. This also allows us to avoid calling lseek() when
the file offset will not be effectively changed. However, if the server
requests some weird offset then we have no choice and will attempt
seeking. Unfortunately, we cannot tell whether it is a genuine failure
or the file system just does not support seeking, so we do not handle
the error further. (One workaround would be to reopen the file and keep
reading it until we're at the correct offset.) In this way we can
support sequential-only file systems if the server requests the contents
sequentially (and it does).
Also note that we do an fstat() right after opening the file in order to
have an accurate value of file size, for this exact file descriptor we
will be using. We should have it filled it by now, but just in case...
There is one more thing to explain. The cbRequested field specifies the
maximum number of bytes the server can handle, not the required number.
Usually this is some power-of-two number like 64 KB, based on the size
of the files on the clipboard. This is why posix_file_read_perform()
does not attempt to fill the whole buffer by repeatedly calling read()
if it has read less data than requested. The server can handle underruns
just fine (and this spares us from special-casing the EOF condition).
This is an example of wClipboardDelegate method implementation. POSIX
subsystem uses synchronous methods, but the interface can be used for
asynchronous request processing as well. The client should call a
Client* callback to request some action and the wClipboard will process
the request and report the result by calling an approriate Clipboard*
callback. Usually there will be two callbacks: one for reporting success
and one to report errors.
All callbacks have at least two arguments: the wClipboardDelegate itself
to pass the system context, and the wClipboard*Request structure with
the arguments to pass the call context. The request context is also
passed to the result callbacks by wClipboard so that the client can
match up the result with its previous request.
The fields of wClipboard*Request structures are heavily influenced by
the MS-RDPECLIP spec and mirror the respective fields of
CLIPRDR_FILECONTENTS_REQUEST. wClipboard should not depend on
MS-RDPECLIP, that's the reason we don't use CLIPRDR_FILECONTENTS_REQUEST
directly. However, I believe that we should not have void* fields in the
request structs so that they can be easily copied around if needed.
This is why have the weird 'streamId' field there which has nothing to
do with wClipboard and will be used only by the clients when sending
replies to the server.
Return values of the callbacks are to be used for reporting errors with
processing the request or reply per se, not for errors encountered while
performing the action requested. Thus, for example, we return NO_ERROR
from posix_file_request_size() even when we fail to report the result to
the client, because we have successfully performed the request and do
not care if the client could not handle our reply for some reason.
Also note that setup_delegate() fills in dummy implementations of
Clipboard* reply callbacks so that we do not crash in case the client
does not fill them and do not have to perform paranoid NULL checks
before calling every single callback.
This is the thing which will be used by clients to request file sizes
and ranges from wClipboard and by wClipboard to report the results of
the requests to the clients.
wClipboard and the client will fill in the (currently absent) callbacks
with their implementations of the request-report interface and will be
using them accordingly.
Initially I thought that wClipbardDelegate would be dynamically
allocated by the client and set into wClipboard (as this would be the
case with a delegate interface implementation in OOP langauges), but
after some thought I ended up with storing the delegate in wClipboard
and using the 'void* custom' field for client-private data.
So the idea is for the subsystem to fill in its callbacks during
wClipboard construction and for the client to get access to
wClipboardDelegate with a getter and fill in its callbacks during its
clipboard initialization. The subsystem will use wClipboard* pointer to
access its data and the client will have its void* pointer to store its
context.
The flags are defined by MS-RDPECLIP 2.2.5.2.3.1 File Descriptor
(CLIPRDR_FILEDESCRIPTOR) as well as by 'File Attribute Constants'
in WinAPI reference [1].
The idea is to delegate FILEDESCRIPTOR format processing to WinPR
instead of cliprdr channel, so move the struct definition there. The
definition used by cliprdr protocol is identical but with some fields
treated as reserved.
The defintions are placed into <winpr/shell.h> as FileGroupDescriptorW
is a shell clipboard format.
Also remove the definition of CLIPRDR_FILELIST. The clients would be
using WinPR to handle the file clipping, so CLIPRDR_FILELIST does not
have to be handled explicitly. The clients will have serialization and
deserialization functions to handle CLIPRDR_FILELIST.
[1]: https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117(v=vs.85).aspx
- fixed invalid, missing or additional arguments
- removed all type casts from arguments
- added missing (void*) typecasts for %p arguments
- use inttypes defines where appropriate
Undefined preprocessor macro in wtypes.h produces:
warning: "__ILP64__" is not defined [-Wundef]
This causes unnecessary hassle to people who compile their FreeRDP-based
applications with -Werror.
- winpr_HMAC_New() now just returnes the opaque WINPR_HMAC_CTX* pointer
which has to be passed to winpr_HMAC_Init() for (re)initialization
and since winpr_HMAC_Final() no more frees the context you always have to
use the new function winpr_HMAC_Free() once winpr_HMAC_New() has succeded
- winpr_Digest_New() now just returns the opaque WINPR_DIGEST_CTX* pointer
which has to be passed to winpr_Digest_Init() for (re)initialization
and since winpr_Digest_Final() no more frees the context you always have to
use the new function winpr_Digest_Free() once winpr_Digest_New() has succeded