FreeRDP
Loading...
Searching...
No Matches
shadow.c
1
19#include <freerdp/config.h>
20
21#include <winpr/crt.h>
22#include <winpr/ssl.h>
23#include <winpr/path.h>
24#include <winpr/cmdline.h>
25#include <winpr/winsock.h>
26
27#include <winpr/tools/makecert.h>
28
29#include <freerdp/server/shadow.h>
30#include <freerdp/settings.h>
31
32#include <freerdp/log.h>
33#define TAG SERVER_TAG("shadow")
34
35WINPR_ATTR_NODISCARD
36static const char* boolstr(BOOL val)
37{
38 return val ? "TRUE" : "FALSE";
39}
40
41static void dump_security_settings(const rdpSettings* settings)
42{
43 WINPR_ASSERT(settings);
44 const BOOL nla = freerdp_settings_get_bool(settings, FreeRDP_NlaSecurity);
45 const BOOL ext = freerdp_settings_get_bool(settings, FreeRDP_ExtSecurity);
46 const BOOL tls = freerdp_settings_get_bool(settings, FreeRDP_TlsSecurity);
47 const BOOL rdp = freerdp_settings_get_bool(settings, FreeRDP_RdpSecurity);
48 const BOOL aad = freerdp_settings_get_bool(settings, FreeRDP_AadSecurity);
49 const BOOL rdstls = freerdp_settings_get_bool(settings, FreeRDP_RdstlsSecurity);
50
51 WLog_INFO(TAG, "security: RDP:%s, TLS:%s, NLA:%s, EXT:%s, AAD:%s, RDSTLS:%s", boolstr(rdp),
52 boolstr(tls), boolstr(nla), boolstr(ext), boolstr(aad), boolstr(rdstls));
53}
54
55int main(int argc, char** argv)
56{
57 int status = 0;
58 DWORD dwExitCode = 0;
59 COMMAND_LINE_ARGUMENT_A shadow_args[] = {
60 { "log-filters", COMMAND_LINE_VALUE_REQUIRED, "<tag>:<level>[,<tag>:<level>[,...]]",
61 nullptr, nullptr, -1, nullptr, "Set logger filters, see wLog(7) for details" },
62 { "log-level", COMMAND_LINE_VALUE_REQUIRED, "[OFF|FATAL|ERROR|WARN|INFO|DEBUG|TRACE]",
63 nullptr, nullptr, -1, nullptr, "Set the default log level, see wLog(7) for details" },
64 { "port", COMMAND_LINE_VALUE_REQUIRED, "<number>", nullptr, nullptr, -1, nullptr,
65 "Server port" },
66 { "ipc-socket", COMMAND_LINE_VALUE_REQUIRED, "<ipc-socket>", nullptr, nullptr, -1, nullptr,
67 "Server IPC socket" },
68 { "bind-address", COMMAND_LINE_VALUE_REQUIRED, "<bind-address>[,<another address>, ...]",
69 nullptr, nullptr, -1, nullptr,
70 "An address to bind to. Use '[<ipv6>]' for IPv6 addresses, e.g. '[::1]' for "
71 "localhost" },
72 { "server-side-cursor", COMMAND_LINE_VALUE_BOOL, nullptr, nullptr, nullptr, -1, nullptr,
73 "hide mouse cursor in RDP client." },
74 { "monitors", COMMAND_LINE_VALUE_OPTIONAL, "<0,1,2...>", nullptr, nullptr, -1, nullptr,
75 "Select or list monitors" },
76 { "subsystem", COMMAND_LINE_VALUE_OPTIONAL, "<name>[,<name>...]", nullptr, nullptr, -1,
77 nullptr, "Subsystems to try, in this order, or list them" },
78 { "max-connections", COMMAND_LINE_VALUE_REQUIRED, "<number>", nullptr, nullptr, -1, nullptr,
79 "maximum connections allowed to server, 0 to deactivate" },
80 { "mouse-relative", COMMAND_LINE_VALUE_BOOL, nullptr, nullptr, nullptr, -1, nullptr,
81 "enable support for relative mouse events" },
82 { "rect", COMMAND_LINE_VALUE_REQUIRED, "<x,y,w,h>", nullptr, nullptr, -1, nullptr,
83 "Select rectangle within monitor to share" },
84 { "auth", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
85 "Clients must authenticate" },
86 { "remote-guard", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse, nullptr, -1, nullptr,
87 "Remote credential guard" },
88 { "restricted-admin", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
89 "Restricted Admin" },
90 { "vmconnect", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse,
91 nullptr, -1, nullptr, "Hyper-V console server (bind on vsock://1)" },
92 { "may-view", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
93 "Clients may view without prompt" },
94 { "may-interact", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
95 "Clients may interact without prompt" },
96 { "sec", COMMAND_LINE_VALUE_REQUIRED, "<rdp|tls|nla|ext>", nullptr, nullptr, -1, nullptr,
97 "force specific protocol security" },
98 { "sec-rdp", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
99 "rdp protocol security" },
100 { "sec-tls", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
101 "tls protocol security" },
102 { "sec-nla", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
103 "nla protocol security" },
104 { "sec-ext", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
105 "nla extended protocol security" },
106 { "sam-file", COMMAND_LINE_VALUE_REQUIRED, "<file>", nullptr, nullptr, -1, nullptr,
107 "NTLM SAM file for NLA authentication" },
108 { "keytab", COMMAND_LINE_VALUE_REQUIRED, "<file>", nullptr, nullptr, -1, nullptr,
109 "Kerberos keytab file for NLA authentication" },
110 { "ccache", COMMAND_LINE_VALUE_REQUIRED, "<file>", nullptr, nullptr, -1, nullptr,
111 "Kerberos host ccache file for NLA authentication" },
112 { "tls-secrets-file", COMMAND_LINE_VALUE_REQUIRED, "<file>", nullptr, nullptr, -1, nullptr,
113 "file where tls secrets shall be stored" },
114 { "nsc", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
115 "Allow NSC codec" },
116 { "rfx", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
117 "Allow RFX surface bits" },
118 { "gfx", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
119 "Allow GFX pipeline" },
120#if defined(WITH_GFX_AV1)
121 { "gfx-av1", COMMAND_LINE_VALUE_OPTIONAL, "[:profile:[low|high|0|1]|off]", BoolValueTrue,
122 nullptr, -1, nullptr, "Allow GFX pipeline AV1 codec extension" },
123#endif
124#if defined(WITH_GFX_AV2)
125 { "gfx-av2", COMMAND_LINE_VALUE_OPTIONAL, "[:profile:[low|high|0|1]|off]", BoolValueTrue,
126 nullptr, -1, nullptr, "Allow GFX pipeline AV2 codec extension" },
127#endif
128 { "gfx-progressive", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
129 "Allow GFX progressive codec" },
130 { "gfx-rfx", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
131 "Allow GFX RFX codec" },
132 { "gfx-planar", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
133 "Allow GFX planar codec" },
134 { "gfx-avc420", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
135 "Allow GFX AVC420 codec" },
136 { "gfx-avc444", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
137 "Allow GFX AVC444 codec" },
138 { "bitmap-compat", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse, nullptr, -1, nullptr,
139 "Limit BitmapUpdate to 1 rectangle (fixes broken windows 11 24H2 clients)" },
140 { "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, nullptr, nullptr,
141 nullptr, -1, nullptr, "Print version" },
142 { "buildconfig", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_BUILDCONFIG, nullptr, nullptr,
143 nullptr, -1, nullptr, "Print the build configuration" },
144 { "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, nullptr, nullptr, nullptr, -1,
145 "?", "Print help" },
146 { nullptr, 0, nullptr, nullptr, nullptr, -1, nullptr, nullptr }
147 };
148
149 shadow_subsystem_set_entry_builtin(nullptr);
150
151 rdpShadowServer* server = shadow_server_new();
152
153 if (!server)
154 {
155 status = -1;
156 WLog_ERR(TAG, "Server new failed");
157 goto fail;
158 }
159
160 {
161 rdpSettings* settings = server->settings;
162 WINPR_ASSERT(settings);
163
164 if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, TRUE) ||
165 !freerdp_settings_set_bool(settings, FreeRDP_ExtSecurity, TRUE) ||
166 !freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE) ||
167 !freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, TRUE))
168 goto fail;
169
170 /* By default allow all GFX modes.
171 * This can be changed with command line flags [+|-]gfx-CODEC
172 */
173 if (!freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, 32) ||
174 !freerdp_settings_set_bool(settings, FreeRDP_NSCodec, TRUE) ||
175 !freerdp_settings_set_bool(settings, FreeRDP_RemoteFxCodec, TRUE) ||
176 !freerdp_settings_set_bool(settings, FreeRDP_RemoteFxImageCodec, TRUE) ||
177 !freerdp_settings_set_uint32(settings, FreeRDP_RemoteFxRlgrMode, RLGR3) ||
178 !freerdp_settings_set_bool(settings, FreeRDP_GfxH264, TRUE) ||
179 !freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444, TRUE) ||
180 !freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444v2, TRUE) ||
181 !freerdp_settings_set_bool(settings, FreeRDP_GfxProgressive, TRUE) ||
182 !freerdp_settings_set_bool(settings, FreeRDP_GfxProgressiveV2, TRUE))
183 goto fail;
184
185 if (!freerdp_settings_set_bool(settings, FreeRDP_MouseUseRelativeMove, FALSE) ||
186 !freerdp_settings_set_bool(settings, FreeRDP_HasRelativeMouseEvent, FALSE))
187 goto fail;
188 }
189
190 if ((status = shadow_server_parse_command_line(server, argc, argv, shadow_args)) < 0)
191 {
192 status = shadow_server_command_line_status_print(server, argc, argv, status, shadow_args);
193 goto fail;
194 }
195
196 if (server->authentication)
197 dump_security_settings(server->settings);
198 else
199 WLog_INFO(TAG, "authentication: disabled");
200
201 if ((status = shadow_server_init(server)) < 0)
202 {
203 WLog_ERR(TAG, "Server initialization failed.");
204 goto fail;
205 }
206
207 if ((status = shadow_server_start(server)) < 0)
208 {
209 WLog_ERR(TAG, "Failed to start server.");
210 goto fail;
211 }
212
213#ifdef _WIN32
214 {
215 MSG msg = WINPR_C_ARRAY_INIT;
216 while (GetMessage(&msg, 0, 0, 0))
217 {
218 TranslateMessage(&msg);
219 DispatchMessage(&msg);
220 }
221 }
222#endif
223
224 (void)WaitForSingleObject(server->thread, INFINITE);
225
226 if (!GetExitCodeThread(server->thread, &dwExitCode))
227 status = -1;
228 else
229 status = (int)dwExitCode;
230
231fail:
232 shadow_server_uninit(server);
233 shadow_server_free(server);
234 return status;
235}
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.