static BOOL TestStream_Rewind(void) { BOOL rc = FALSE; wStream* s = Stream_New(NULL, 100); if (!s) goto out; if (s->pointer != s->buffer) goto out; Stream_Seek(s, 100); if (s->pointer != s->buffer + 100) goto out; Stream_Rewind(s, 10); if (s->pointer != s->buffer + 90) goto out; Stream_Rewind_UINT8(s); if (s->pointer != s->buffer + 89) goto out; Stream_Rewind_UINT16(s); if (s->pointer != s->buffer + 87) goto out; Stream_Rewind_UINT32(s); if (s->pointer != s->buffer + 83) goto out; Stream_Rewind_UINT64(s); if (s->pointer != s->buffer + 75) goto out; rc = TRUE; out: Stream_Free(s, TRUE); return rc; }
wStream* http_request_write(HttpContext* http_context, HttpRequest* http_request) { int i; wStream* s; int length = 0; http_request->count = 9; http_request->lines = (char**) malloc(sizeof(char*) * http_request->count); http_request->lines[0] = http_encode_header_line(http_request->Method, http_request->URI); http_request->lines[1] = http_encode_body_line("Cache-Control", http_context->CacheControl); http_request->lines[2] = http_encode_body_line("Connection", http_context->Connection); http_request->lines[3] = http_encode_body_line("Pragma", http_context->Pragma); http_request->lines[4] = http_encode_body_line("Accept", http_context->Accept); http_request->lines[5] = http_encode_body_line("User-Agent", http_context->UserAgent); http_request->lines[6] = http_encode_content_length_line(http_request->ContentLength); http_request->lines[7] = http_encode_body_line("Host", http_context->Host); if (http_request->Authorization != NULL) { http_request->lines[8] = http_encode_body_line("Authorization", http_request->Authorization); } else if ((http_request->AuthScheme != NULL) && (http_request->AuthParam != NULL)) { http_request->lines[8] = http_encode_authorization_line(http_request->AuthScheme, http_request->AuthParam); } for (i = 0; i < http_request->count; i++) { length += (strlen(http_request->lines[i]) + 2); /* add +2 for each '\r\n' character */ } length += 2; /* empty line "\r\n" at end of header */ length += 1; /* null terminator */ s = Stream_New(NULL, length); for (i = 0; i < http_request->count; i++) { Stream_Write(s, http_request->lines[i], strlen(http_request->lines[i])); Stream_Write(s, "\r\n", 2); free(http_request->lines[i]); } Stream_Write(s, "\r\n", 2); free(http_request->lines); Stream_Write(s, "\0", 1); /* append null terminator */ Stream_Rewind(s, 1); /* don't include null terminator in length */ Stream_Length(s) = Stream_GetPosition(s); return s; }
BOOL ber_read_contextual_tag(wStream* s, BYTE tag, int* length, BOOL pc) { BYTE byte; if (Stream_GetRemainingLength(s) < 1) return FALSE; Stream_Read_UINT8(s, byte); if (byte != ((BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag))) { Stream_Rewind(s, 1); return FALSE; } return ber_read_length(s, length); }
static BOOL nego_read_request_token_or_cookie(rdpNego* nego, wStream* s) { /* routingToken and cookie are optional and mutually exclusive! * * routingToken (variable): An optional and variable-length routing * token (used for load balancing) terminated by a 0x0D0A two-byte * sequence: (check [MSFT-SDLBTS] for details!) * Cookie:[space]msts=[ip address].[port].[reserved][\x0D\x0A] * * cookie (variable): An optional and variable-length ANSI character * string terminated by a 0x0D0A two-byte sequence: * Cookie:[space]mstshash=[ANSISTRING][\x0D\x0A] */ BYTE *str = NULL; UINT16 crlf = 0; int pos, len; BOOL result = FALSE; BOOL isToken = FALSE; str = Stream_Pointer(s); pos = Stream_GetPosition(s); /* minimum length for cookie is 15 */ if (Stream_GetRemainingLength(s) < 15) return TRUE; if (!memcmp(Stream_Pointer(s), "Cookie: msts=", 13)) { isToken = TRUE; Stream_Seek(s, 13); } else { /* not a cookie, minimum length for token is 19 */ if (Stream_GetRemainingLength(s) < 19) return TRUE; if (memcmp(Stream_Pointer(s), "Cookie: mstshash=", 17)) return TRUE; Stream_Seek(s, 17); } while (Stream_GetRemainingLength(s) >= 2) { Stream_Read_UINT16(s, crlf); if (crlf == 0x0A0D) break; Stream_Rewind(s, 1); } if (crlf == 0x0A0D) { Stream_Rewind(s, 2); len = Stream_GetPosition(s) - pos; Stream_Write_UINT16(s, 0); if (strlen((char*)str) == len) { if (isToken) result = nego_set_routing_token(nego, str, len); else result = nego_set_cookie(nego, (char*)str); } } if (!result) { Stream_SetPosition(s, pos); WLog_ERR(TAG, "invalid %s received", isToken ? "routing token" : "cookie"); } else { WLog_DBG(TAG, "received %s [%s]", isToken ? "routing token" : "cookie", str); } return result; }
wStream* http_request_write(HttpContext* http_context, HttpRequest* http_request) { int i, count; char** lines; wStream* s; int length = 0; count = 0; lines = (char**) calloc(32, sizeof(char*)); if (!lines) return NULL; lines[count++] = http_encode_header_line(http_request->Method, http_request->URI); lines[count++] = http_encode_body_line("Cache-Control", http_context->CacheControl); lines[count++] = http_encode_body_line("Connection", http_context->Connection); lines[count++] = http_encode_body_line("Pragma", http_context->Pragma); lines[count++] = http_encode_body_line("Accept", http_context->Accept); lines[count++] = http_encode_body_line("User-Agent", http_context->UserAgent); lines[count++] = http_encode_content_length_line(http_request->ContentLength); lines[count++] = http_encode_body_line("Host", http_context->Host); /* check that everything went well */ for (i = 0; i < count; i++) { if (!lines[i]) goto out_free; } if (http_request->Authorization) { lines[count] = http_encode_body_line("Authorization", http_request->Authorization); if (!lines[count]) goto out_free; count++; } else if (http_request->AuthScheme && http_request->AuthParam) { lines[count] = http_encode_authorization_line(http_request->AuthScheme, http_request->AuthParam); if (!lines[count]) goto out_free; count++; } for (i = 0; i < count; i++) { length += (strlen(lines[i]) + 2); /* add +2 for each '\r\n' character */ } length += 2; /* empty line "\r\n" at end of header */ length += 1; /* null terminator */ s = Stream_New(NULL, length); if (!s) goto out_free; for (i = 0; i < count; i++) { Stream_Write(s, lines[i], strlen(lines[i])); Stream_Write(s, "\r\n", 2); free(lines[i]); } Stream_Write(s, "\r\n", 2); free(lines); Stream_Write(s, "\0", 1); /* append null terminator */ Stream_Rewind(s, 1); /* don't include null terminator in length */ Stream_Length(s) = Stream_GetPosition(s); return s; out_free: for (i = 0; i < 9; i++) { if (lines[i]) free(lines[i]); } free(lines); return NULL; }
static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s) { UINT16 length; UINT16 pduType; UINT16 pduLength; UINT16 pduSource; UINT16 channelId = 0; UINT16 securityFlags; int nextPosition; if (!rdp_read_header(rdp, s, &length, &channelId)) { DEBUG_WARN( "Incorrect RDP header.\n"); return -1; } if (rdp->settings->DisableEncryption) { if (!rdp_read_security_header(s, &securityFlags)) return -1; if (securityFlags & (SEC_ENCRYPT | SEC_REDIRECTION_PKT)) { if (!rdp_decrypt(rdp, s, length - 4, securityFlags)) { DEBUG_WARN( "rdp_decrypt failed\n"); return -1; } } if (securityFlags & SEC_REDIRECTION_PKT) { /* * [MS-RDPBCGR] 2.2.13.2.1 * - no share control header, nor the 2 byte pad */ Stream_Rewind(s, 2); return rdp_recv_enhanced_security_redirection_packet(rdp, s); } } if (channelId == MCS_GLOBAL_CHANNEL_ID) { while (Stream_GetRemainingLength(s) > 3) { nextPosition = Stream_GetPosition(s); if (!rdp_read_share_control_header(s, &pduLength, &pduType, &pduSource)) return -1; nextPosition += pduLength; rdp->settings->PduSource = pduSource; switch (pduType) { case PDU_TYPE_DATA: if (rdp_recv_data_pdu(rdp, s) < 0) { DEBUG_WARN( "rdp_recv_data_pdu failed\n"); return -1; } break; case PDU_TYPE_DEACTIVATE_ALL: if (!rdp_recv_deactivate_all(rdp, s)) return -1; break; case PDU_TYPE_SERVER_REDIRECTION: return rdp_recv_enhanced_security_redirection_packet(rdp, s); break; default: DEBUG_WARN( "incorrect PDU type: 0x%04X\n", pduType); break; } Stream_SetPosition(s, nextPosition); } } else if (rdp->mcs->messageChannelId && channelId == rdp->mcs->messageChannelId) { return rdp_recv_message_channel_pdu(rdp, s); } else { if (!freerdp_channel_process(rdp->instance, s, channelId)) return -1; } return 0; }
int license_recv(rdpLicense* license, wStream* s) { BYTE flags; BYTE bMsgType; UINT16 wMsgSize; UINT16 length; UINT16 channelId; UINT16 securityFlags; if (!rdp_read_header(license->rdp, s, &length, &channelId)) { WLog_ERR(TAG, "Incorrect RDP header."); return -1; } if (!rdp_read_security_header(s, &securityFlags)) return -1; if (securityFlags & SEC_ENCRYPT) { if (!rdp_decrypt(license->rdp, s, length - 4, securityFlags)) { WLog_ERR(TAG, "rdp_decrypt failed"); return -1; } } if (!(securityFlags & SEC_LICENSE_PKT)) { int status; if (!(securityFlags & SEC_ENCRYPT)) Stream_Rewind(s, RDP_SECURITY_HEADER_LENGTH); status = rdp_recv_out_of_sequence_pdu(license->rdp, s); if (status < 0) { WLog_ERR(TAG, "unexpected license packet."); return status; } return 0; } if (!license_read_preamble(s, &bMsgType, &flags, &wMsgSize)) /* preamble (4 bytes) */ return -1; DEBUG_LICENSE("Receiving %s Packet", LICENSE_MESSAGE_STRINGS[bMsgType & 0x1F]); switch (bMsgType) { case LICENSE_REQUEST: if (!license_read_license_request_packet(license, s)) return -1; if (!license_send_new_license_request_packet(license)) return -1; break; case PLATFORM_CHALLENGE: if (!license_read_platform_challenge_packet(license, s)) return -1; if (!license_send_platform_challenge_response_packet(license)) return -1; break; case NEW_LICENSE: license_read_new_license_packet(license, s); break; case UPGRADE_LICENSE: license_read_upgrade_license_packet(license, s); break; case ERROR_ALERT: if (!license_read_error_alert_packet(license, s)) return -1; break; default: WLog_ERR(TAG, "invalid bMsgType:%d", bMsgType); return FALSE; } return 0; }
void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); if (context->custom) { UINT32 index; int formatNameLength; CLIPRDR_FORMAT* formats; CLIPRDR_FORMAT_LIST formatList; formatList.msgType = CB_FORMAT_LIST; formatList.msgFlags = msgFlags; formatList.dataLen = dataLen; formatList.cFormats = 0; while (dataLen) { Stream_Seek(s, 4); /* formatId */ dataLen -= 4; formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s)); Stream_Seek(s, (formatNameLength + 1) * 2); dataLen -= ((formatNameLength + 1) * 2); formatList.cFormats++; } index = 0; dataLen = formatList.dataLen; Stream_Rewind(s, dataLen); formats = (CLIPRDR_FORMAT*) malloc(sizeof(CLIPRDR_FORMAT) * formatList.cFormats); formatList.formats = formats; while (dataLen) { Stream_Read_UINT32(s, formats[index].formatId); /* formatId */ dataLen -= 4; formats[index].formatName = NULL; formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s)); if (formatNameLength) { formatNameLength = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), -1, &(formats[index].formatName), 0, NULL, NULL); Stream_Seek(s, formatNameLength * 2); dataLen -= (formatNameLength * 2); } else { Stream_Seek(s, 2); dataLen -= 2; } index++; } if (context->ServerFormatList) context->ServerFormatList(context, &formatList); for (index = 0; index < formatList.cFormats; index++) free(formats[index].formatName); free(formats); } else { int i; UINT32 format; BOOL supported; CLIPRDR_FORMAT_NAME* format_name; RDP_CB_FORMAT_LIST_EVENT* cb_event; cb_event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL); if (dataLen > 0) { cb_event->raw_format_data = (BYTE*) malloc(dataLen); memcpy(cb_event->raw_format_data, Stream_Pointer(s), dataLen); cb_event->raw_format_data_size = dataLen; cb_event->raw_format_unicode = (msgFlags & CB_ASCII_NAMES) ? FALSE : TRUE; } if (cliprdr->use_long_format_names) cliprdr_process_long_format_names(cliprdr, s, dataLen, msgFlags); else cliprdr_process_short_format_names(cliprdr, s, dataLen, msgFlags); if (cliprdr->num_format_names > 0) cb_event->formats = (UINT32*) malloc(sizeof(UINT32) * cliprdr->num_format_names); cb_event->num_formats = 0; for (i = 0; i < cliprdr->num_format_names; i++) { supported = TRUE; format_name = &cliprdr->format_names[i]; format = format_name->id; switch (format) { case CB_FORMAT_TEXT: case CB_FORMAT_DIB: case CB_FORMAT_UNICODETEXT: break; default: if (format_name->length > 0) { DEBUG_CLIPRDR("format: %s", format_name->name); if (strcmp(format_name->name, "HTML Format") == 0) { format = CB_FORMAT_HTML; break; } if (strcmp(format_name->name, "PNG") == 0) { format = CB_FORMAT_PNG; break; } if (strcmp(format_name->name, "JFIF") == 0) { format = CB_FORMAT_JPEG; break; } if (strcmp(format_name->name, "GIF") == 0) { format = CB_FORMAT_GIF; break; } } else { supported = FALSE; } break; } if (supported) cb_event->formats[cb_event->num_formats++] = format; if (format_name->length > 0) free(format_name->name); } free(cliprdr->format_names); cliprdr->format_names = NULL; cliprdr->num_format_names = 0; svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); cliprdr_send_format_list_response(cliprdr); } }