15#include <openssl/bio.h>
18#include <winpr/stream.h>
19#include <winpr/wlog.h>
21#include <freerdp/client.h>
24#include "../gateway/http.h"
25#include "../gateway/rpc.h"
26#include "../gateway/rts.h"
27#include "../gateway/rts_signature.h"
28#include "../gateway/tsg.h"
29#include "../gateway/websocket.h"
30#include "../../crypto/tls.h"
34 const RtsPduSignature* known[] = { &RTS_PDU_CONN_A3_SIGNATURE, &RTS_PDU_CONN_C2_SIGNATURE,
35 &RTS_PDU_OUT_R1_A2_SIGNATURE, &RTS_PDU_PING_SIGNATURE,
36 &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE };
37 const size_t start = Stream_GetPosition(s);
40 if (rts_read_pdu_header(s, &header) && (header.common.ptype == PTYPE_RTS))
43 if (rts_extract_pdu_signature(&signature, s, &header))
44 (void)rts_identify_pdu_signature(&signature,
nullptr);
46 rts_free_pdu_header(&header, FALSE);
48 for (
size_t x = 0; x < ARRAYSIZE(known); x++)
50 if (!Stream_SetPosition(s, start))
52 (void)rts_match_pdu_signature(known[x], s,
nullptr);
56static void fuzz_tsg(rdpContext* context,
wStream* s)
58 if (Stream_GetRemainingLength(s) < 2)
61 const BYTE state = Stream_Get_UINT8(s);
62 const BYTE flags = Stream_Get_UINT8(s);
63 const TSG_STATE selectedState = (TSG_STATE)(state % (TSG_STATE_FINAL + 1));
64 if (selectedState == TSG_STATE_TUNNEL_CLOSE_PENDING)
67 rdpTsg* tsg = tsg_new(context->rdp->transport);
71 if (tsg_set_state(tsg, selectedState))
73 RPC_PDU pdu = WINPR_C_ARRAY_INIT;
75 pdu.Flags = (flags & 0x01) ? RPC_PDU_FLAG_STUB : 0;
76 pdu.Type = PTYPE_RESPONSE;
77 (void)tsg_recv_pdu(tsg, &pdu);
82static void fuzz_http(rdpContext* context,
wStream* s)
84 if ((Stream_GetRemainingLength(s) < 1) || (Stream_GetRemainingLength(s) > INT32_MAX))
87 const BOOL readContentLength = (Stream_Get_UINT8(s) & 0x01) != 0;
88 HttpContext* http = http_context_new();
89 BIO* bio = BIO_new_mem_buf(Stream_ConstPointer(s), (
int)Stream_GetRemainingLength(s));
95 rdpTls tls = WINPR_C_ARRAY_INIT;
97 tls.context = context;
99 HttpResponse* response = http_response_recv(&tls, readContentLength);
102 (void)http_response_get_status_code(response);
103 (void)http_response_get_body_length(response);
104 (void)http_response_get_body(response);
105 (void)http_response_get_auth_token(response,
"NTLM");
106 (void)http_response_get_auth_token(response,
"Negotiate");
107 (void)http_response_get_setcookie(response,
"RdgAuthToken");
108 (void)http_response_get_transfer_encoding(response);
109 (void)http_response_extract_cookies(response, http);
110 (void)http_context_enable_websocket_upgrade(http, TRUE);
111 (void)http_response_is_websocket(http, response);
112 http_response_free(response);
118 http_context_free(http);
121static void fuzz_websocket(
wStream* s)
123 if (Stream_GetRemainingLength(s) > INT32_MAX)
126 websocket_context* ws = websocket_context_new();
128 BIO* bio = BIO_new_mem_buf(Stream_ConstPointer(s), (
int)Stream_GetRemainingLength(s));
132 for (
size_t x = 0; x < 64; x++)
134 BYTE buffer[1024] = WINPR_C_ARRAY_INIT;
135 if (websocket_context_read(ws, bio, buffer,
sizeof(buffer)) <= 0)
141 websocket_context_free(ws);
144int LLVMFuzzerTestOneInput(
const uint8_t* data,
size_t size)
146 if ((size < 1) || (size > (1u << 20)))
149 wLog* root = WLog_GetRoot();
150 (void)WLog_SetLogLevel(root, WLOG_TRACE);
151 (void)WLog_SetLogAppenderType(root, WLOG_APPENDER_CALLBACK);
153 wStream buffer = WINPR_C_ARRAY_INIT;
154 wStream* s = Stream_StaticConstInit(&buffer, data, size);
155 const BYTE target = Stream_Get_UINT8(s);
167 RDP_CLIENT_ENTRY_POINTS entry = WINPR_C_ARRAY_INIT;
168 entry.Version = RDP_CLIENT_INTERFACE_VERSION;
169 entry.Size =
sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
170 entry.ContextSize =
sizeof(rdpContext);
172 rdpContext* context = freerdp_client_context_new(&entry);
179 if ((target % 4) == 1)
180 fuzz_tsg(context, s);
182 fuzz_http(context, s);
184 freerdp_client_context_free(context);
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.