Пример #1
0
/* Process a new licence packet */
static void
licence_process_new_license(STREAM s)
{
	RDSSL_RC4 crypt_key;
	uint32 length;
	int i;

	in_uint8s(s, 2);	// Skip license binary blob type
	in_uint16_le(s, length);
	if (!s_check_rem(s, length))
		return;

	rdssl_rc4_set_key(&crypt_key, g_licence_key, 16);
	rdssl_rc4_crypt(&crypt_key, s->p, s->p, length);

	/* Parse NEW_LICENSE_INFO block */
	in_uint8s(s, 4);	// skip dwVersion

	/* Skip strings, Scope, CompanyName and ProductId to get
	   to the LicenseInfo which we store in license blob. */
	length = 0;
	for (i = 0; i < 4; i++)
	{
		in_uint8s(s, length);
		in_uint32_le(s, length);
		if (!s_check_rem(s, length))
			return;
	}

	g_licence_issued = True;
	save_licence(s->p, length);
}
Пример #2
0
/* returns error */
static int APP_CC
process_message(void)
{
    struct stream *s = (struct stream *)NULL;
    int size = 0;
    int id = 0;
    int rv = 0;
    char *next_msg = (char *)NULL;

    if (g_con_trans == 0)
    {
        return 1;
    }

    s = trans_get_in_s(g_con_trans);

    if (s == 0)
    {
        return 1;
    }

    rv = 0;

    while (s_check_rem(s, 8))
    {
        next_msg = s->p;
        in_uint32_le(s, id);
        in_uint32_le(s, size);
        next_msg += size;

        switch (id)
        {
            case 1: /* init */
                rv = process_message_init(s);
                break;
            case 3: /* channel setup */
                rv = process_message_channel_setup(s);
                break;
            case 5: /* channel data */
                rv = process_message_channel_data(s);
                break;
            case 7: /* channel data response */
                rv = process_message_channel_data_response(s);
                break;
            default:
                LOGM((LOG_LEVEL_ERROR, "process_message: error in process_message ",
                      "unknown msg %d", id));
                break;
        }

        if (rv != 0)
        {
            break;
        }

        s->p = next_msg;
    }

    return rv;
}
Пример #3
0
int 
clipboard_c2s_in_files(struct stream *s, char *file_list)
{
    int cItems;
    int lindex;
    int str_len;
    struct clip_file_desc *cfd;
    char *ptr;

    if (!s_check_rem(s, 4))
    {
        LLOGLN(0, ("clipboard_c2s_in_files: parse error"));
        return 1;
    }
    in_uint32_le(s, cItems);
    if (cItems > 64 * 1024) /* sanity check */
    {
        LLOGLN(0, ("clipboard_c2s_in_files: error cItems %d too big", cItems));
        return 1;
    }
    xfuse_clear_clip_dir();
    LLOGLN(10, ("clipboard_c2s_in_files: cItems %d", cItems));
    cfd = (struct clip_file_desc *)
          g_malloc(sizeof(struct clip_file_desc), 0);
    ptr = file_list;
    for (lindex = 0; lindex < cItems; lindex++)
    {
        g_memset(cfd, 0, sizeof(struct clip_file_desc));
        clipboard_c2s_in_file_info(s, cfd);
        if ((g_pos(cfd->cFileName, "\\") >= 0) ||
            (cfd->fileAttributes & CB_FILE_ATTRIBUTE_DIRECTORY))
        {
            LLOGLN(0, ("clipboard_c2s_in_files: skipping directory not "
                       "supported [%s]", cfd->cFileName));
            continue;
        }
        xfuse_add_clip_dir_item(cfd->cFileName, 0, cfd->fileSizeLow, lindex);

        g_strcpy(ptr, "file://");
        ptr += 7;

        str_len = g_strlen(g_fuse_clipboard_path);
        g_strcpy(ptr, g_fuse_clipboard_path);
        ptr += str_len;

        *ptr = '/';
        ptr++;

        str_len = g_strlen(cfd->cFileName);
        g_strcpy(ptr, cfd->cFileName);
        ptr += str_len;

        *ptr = '\n';
        ptr++;
    }
    *ptr = 0;
    g_free(cfd);
    return 0;
}
Пример #4
0
/* Process a Server New (or Upgrade) License packet */
static void
licence_process_new_license(rdpLicence * licence, STREAM s)
{
    int i;
    uint32 length;
    uint32 os_major;
    uint32 os_minor;
    CryptoRc4 crypt_key;

    /* Licensing Binary BLOB with EncryptedLicenseInfo: */
    in_uint8s(s, 2);	/* wBlobType should be 0x0009 (BB_ENCRYPTED_DATA_BLOB) */
    in_uint16_le(s, length);	/* wBlobLen */

    /* RC4-encrypted New License Information */
    if (!s_check_rem(s, length))
        return;

    crypt_key = crypto_rc4_init(licence->licence_key, 16);
    crypto_rc4(crypt_key, length, s->p, s->p);	/* decrypt in place */
    crypto_rc4_free(crypt_key);

    /* dwVersion */
    in_uint16_le(s, os_major);	/* OS major version */
    in_uint16_le(s, os_minor);	/* OS minor version */

    /* Skip Scope, CompanyName and ProductId */
    for (i = 0; i < 3; i++)
    {
        in_uint32_le(s, length);
        if (!s_check_rem(s, length))
            return;
        in_uint8s(s, length);
    }

    /* LicenseInfo - CAL from license server */
    in_uint32_le(s, length);
    if (!s_check_rem(s, length))
        return;
    licence->licence_issued = True;
    save_licence(s->p, length);
}
Пример #5
0
/* returns error */
	static int APP_CC
process_message(void)
{
	struct stream* s;
	int size;
	int id;
	int rv;
	char* next_msg;

	if (g_con_trans == 0)
	{
		return 1;
	}
	s = trans_get_in_s(g_con_trans);
	if (s == 0)
	{
		return 1;
	}
	rv = 0;
	while (s_check_rem(s, 8))
	{
		next_msg = s->p;
		in_uint32_le(s, id);
		in_uint32_le(s, size);
		next_msg += size;
		switch (id)
		{
			case 1: /* init */
				rv = process_message_init(s);
				break;
			case 3: /* channel setup */
				rv = process_message_channel_setup(s);
				break;
			case 5: /* channel data */
				rv = process_message_channel_data(s);
				break;
			case 7: /* channel data response */
				rv = process_message_channel_data_response(s);
				break;
			default:
				log_message(&log_conf, LOG_LEVEL_DEBUG, "chansrv[process_message]: "
						"unknown msg %d", id);
				break;
		}
		if (rv != 0)
		{
			break;
		}
		s->p = next_msg;
	}
	return rv;
}
Пример #6
0
/* Process an licence issue packet */
static void
licence_process_issue(STREAM s)
{
	void * crypt_key;
	uint32 length;
	uint16 check;
	int i;

	in_uint8s(s, 2);	/* 3d 45 - unknown */
	in_uint16_le(s, length);
	if (!s_check_rem(s, length))
		return;

	crypt_key = ssl_rc4_info_create();
	ssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
	ssl_rc4_crypt(crypt_key, (char *)s->p, (char *)s->p, length);
	ssl_rc4_info_delete(crypt_key);

	in_uint16(s, check);
	if (check != 0)
		return;

	g_licence_issued = True;

	in_uint8s(s, 2);	/* pad */

	/* advance to fourth string */
	length = 0;
	for (i = 0; i < 4; i++)
	{
		in_uint8s(s, length);
		in_uint32_le(s, length);
		if (!s_check_rem(s, length))
			return;
	}

	g_licence_issued = True;
	save_licence(s->p, length);
}
Пример #7
0
/* Process an licence issue packet */
static void
licence_process_issue(RDPCLIENT * This, STREAM s)
{
	RC4_KEY crypt_key;
	uint32 length;
	uint16 check;
	int i;

	in_uint8s(s, 2);	/* 3d 45 - unknown */
	in_uint16_le(s, length);
	if (!s_check_rem(s, length))
		return;

	RC4_set_key(&crypt_key, 16, This->licence.key);
	RC4(&crypt_key, length, s->p, s->p);

	in_uint16(s, check);
	if (check != 0)
		return;

	This->licence_issued = True;

	in_uint8s(s, 2);	/* pad */

	/* advance to fourth string */
	length = 0;
	for (i = 0; i < 4; i++)
	{
		in_uint8s(s, length);
		in_uint32_le(s, length);
		if (!s_check_rem(s, length))
			return;
	}

	This->licence_issued = True;
	save_licence(This, s->p, length);
}
Пример #8
0
/* Process an licence issue packet */
static void
licence_process_issue(RDConnectionRef conn, RDStreamRef s)
{
	RC4_KEY crypt_key;
	uint32 length;
	uint16 check;
	int i;

	in_uint8s(s, 2);	/* 3d 45 - unknown */
	in_uint16_le(s, length);
	if (!s_check_rem(s, length))
		return;

	RC4_set_key(&crypt_key, 16, conn->licenseKey);
	RC4(&crypt_key, length, s->p, s->p);

	in_uint16(s, check);
	if (check != 0)
		return;

	conn->licenseIssued = True;

	in_uint8s(s, 2);	/* pad */

	/* advance to fourth string */
	length = 0;
	for (i = 0; i < 4; i++)
	{
		in_uint8s(s, length);
		in_uint32_le(s, length);
		if (!s_check_rem(s, length))
			return;
	}

	conn->licenseIssued = True;
	save_licence(s->p, length);
}
Пример #9
0
/* returns error
   process a message for the channel handler */
static int APP_CC
xrdp_mm_chan_process_msg(struct xrdp_mm* self, struct trans* trans,
                         struct stream* s)
{
  int rv = 0;
  int id = 0;
  int size = 0;
  char* next_msg = (char *)NULL;

  rv = 0;
  while (s_check_rem(s, 8))
  {
    next_msg = s->p;
    in_uint32_le(s, id);
    in_uint32_le(s, size);
    next_msg += size;
    switch (id)
    {
      case 2: /* channel init response */
        rv = xrdp_mm_trans_process_init_response(self, trans);
        break;
      case 4: /* channel setup response */
        break;
      case 6: /* channel data response */
        break;
      case 8: /* channel data */
        rv = xrdp_mm_trans_process_channel_data(self, trans);
        break;
      default:
        g_writeln("xrdp_mm_chan_process_msg: unknown id %d", id);
        break;
    }
    if (rv != 0)
    {
      break;
    }
    s->p = next_msg;
  }
  return rv;
}
Пример #10
0
/* Process an licence issue packet */
static void
licence_process_issue(STREAM s)
{
	RC4_KEY crypt_key;
	uint32 length;
	uint16 check;

	in_uint8s(s, 2);	/* 3d 45 - unknown */
	in_uint16_le(s, length);
	if (!s_check_rem(s, length))
		return;

	RC4_set_key(&crypt_key, 16, licence_key);
	RC4(&crypt_key, length, s->p, s->p);

	in_uint16(s, check);
	if (check != 0)
		return;

	licence_issued = True;
	save_licence(s->p, length-2);
}
Пример #11
0
/* Establish a connection up to the ISO layer */
RD_BOOL
iso_connect(char *server, char *username, RD_BOOL reconnect, uint32 * selected_protocol)
{
	STREAM s;
	uint8 code;

	g_negotiate_rdp_protocol = True;

      retry:
	*selected_protocol = PROTOCOL_RDP;
	code = 0;

	if (!tcp_connect(server))
		return False;

	if (reconnect)
	{
		iso_send_msg(ISO_PDU_CR);
	}
	else
	{
		iso_send_connection_request(username);
	}

	s = iso_recv_msg(&code, NULL);
	if (s == NULL)
		return False;

	if (code != ISO_PDU_CC)
	{
		error("expected CC, got 0x%x\n", code);
		tcp_disconnect();
		return False;
	}

	if (g_rdp_version >= RDP_V5 && s_check_rem(s, 8))
	{
		/* handle RDP_NEG_REQ response */
		const char *reason = NULL;

		uint8 type = 0, flags = 0;
		uint16 length = 0;
		uint32 data = 0;

		in_uint8(s, type);
		in_uint8(s, flags);
		in_uint16(s, length);
		in_uint32(s, data);

		if (type == RDP_NEG_FAILURE)
		{
			switch (data)
			{
				case SSL_REQUIRED_BY_SERVER:
					reason = "SSL required by server";
					break;
				case SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER:
					reason = "SSL with user authentication required by server";
					break;
				case SSL_NOT_ALLOWED_BY_SERVER:
					reason = "SSL not allowed by server";
					break;
				case SSL_CERT_NOT_ON_SERVER:
					reason = "SSL certificated not on server";
					break;
				case INCONSISTENT_FLAGS:
					reason = "inconsistent flags";
					break;
				case HYBRID_REQUIRED_BY_SERVER:
					reason = "hybrid authentication (CredSSP) required by server";
					break;
				default:
					reason = "unknown reason";
			}

			tcp_disconnect();
			warning("RDP protocol negotiation failed with reason: %s (error 0x%x),\n",
				reason, data);
			warning("retrying without negotiation using plain RDP protocol.\n");

			g_negotiate_rdp_protocol = False;
			goto retry;
		}

		if (type != RDP_NEG_RSP)
		{
			tcp_disconnect();
			error("expected RDP_NEG_RSP, got type = 0x%x\n", type);
			warning("retrying without negotiation using plain RDP protocol.\n");

			g_negotiate_rdp_protocol = False;
			goto retry;
		}

		/* handle negotiation response */
		if (data == PROTOCOL_SSL)
		{
			DEBUGMSG(1,(L"iso_connect: negotiation: PROTOCOL_SSL\n"));
			if (!tcp_tls_connect())
			{
				tcp_disconnect();
				DEBUGMSG(1,(L"iso_connect: negotiation: PROTOCOL_SSL FAILED\n"));
				return False;
			}

			/* do not use encryption when using TLS */
			g_encryption = False;
		}
		else if (data != PROTOCOL_RDP)
		{
			tcp_disconnect();
			error("unexpected protocol in neqotiation response, got data = 0x%x.\n",
			      data);
			return False;
		}

		*selected_protocol = data;
	}
	return True;
}
Пример #12
0
int APP_CC
xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
{
    int cap_len;
    int source_len;
    int num_caps;
    int index;
    int type;
    int len;
    char *p;

    DEBUG(("in xrdp_caps_process_confirm_active"));
    in_uint8s(s, 4); /* rdp_shareid */
    in_uint8s(s, 2); /* userid */
    in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */
    in_uint16_le(s, cap_len);
    in_uint8s(s, source_len);
    in_uint16_le(s, num_caps);
    in_uint8s(s, 2); /* pad */

    if ((cap_len < 0) || (cap_len > 1024 * 1024))
    {
        return 1;
    }

    for (index = 0; index < num_caps; index++)
    {
        p = s->p;
        if (!s_check_rem(s, 4))
        {
            g_writeln("xrdp_caps_process_confirm_active: error 1");
            return 1;
        }
        in_uint16_le(s, type);
        in_uint16_le(s, len);
        if ((len < 4) || !s_check_rem(s, len - 4))
        {
            g_writeln("xrdp_caps_process_confirm_active: error: len %d, "
                      "remaining %d", len, (int) (s->end - s->p));
            return 1;
        }
        len -= 4;
        switch (type)
        {
            case RDP_CAPSET_GENERAL: /* 1 */
                DEBUG(("RDP_CAPSET_GENERAL"));
                xrdp_caps_process_general(self, s, len);
                break;
            case RDP_CAPSET_BITMAP: /* 2 */
                DEBUG(("RDP_CAPSET_BITMAP"));
                break;
            case RDP_CAPSET_ORDER: /* 3 */
                DEBUG(("RDP_CAPSET_ORDER"));
                xrdp_caps_process_order(self, s, len);
                break;
            case RDP_CAPSET_BMPCACHE: /* 4 */
                DEBUG(("RDP_CAPSET_BMPCACHE"));
                xrdp_caps_process_bmpcache(self, s, len);
                break;
            case RDP_CAPSET_CONTROL: /* 5 */
                DEBUG(("RDP_CAPSET_CONTROL"));
                break;
            case 6:
                xrdp_caps_process_cache_v3_codec_id(self, s, len);
                break;
            case RDP_CAPSET_ACTIVATE: /* 7 */
                DEBUG(("RDP_CAPSET_ACTIVATE"));
                break;
            case RDP_CAPSET_POINTER: /* 8 */
                DEBUG(("RDP_CAPSET_POINTER"));
                xrdp_caps_process_pointer(self, s, len);
                break;
            case RDP_CAPSET_SHARE: /* 9 */
                DEBUG(("RDP_CAPSET_SHARE"));
                break;
            case RDP_CAPSET_COLCACHE: /* 10 */
                DEBUG(("RDP_CAPSET_COLCACHE"));
                break;
            case 12: /* 12 */
                DEBUG(("--12"));
                break;
            case 13: /* 13 */
                xrdp_caps_process_input(self, s, len);
                break;
            case 14: /* 14 */
                DEBUG(("--14"));
                break;
            case RDP_CAPSET_BRUSHCACHE: /* 15 */
                xrdp_caps_process_brushcache(self, s, len);
                break;
            case 16: /* 16 */
                DEBUG(("--16"));
                break;
            case 17: /* 17 */
                DEBUG(("CAPSET_TYPE_OFFSCREEN_CACHE"));
                xrdp_caps_process_offscreen_bmpcache(self, s, len);
                break;
            case RDP_CAPSET_BMPCACHE2: /* 19 */
                DEBUG(("RDP_CAPSET_BMPCACHE2"));
                xrdp_caps_process_bmpcache2(self, s, len);
                break;
            case 20: /* 20 */
                DEBUG(("--20"));
                break;
            case 21: /* 21 */
                DEBUG(("--21"));
                break;
            case 22: /* 22 */
                DEBUG(("--22"));
                break;
            case 0x0017: /* 23 CAPSETTYPE_RAIL */
                xrdp_caps_process_rail(self, s, len);
                break;
            case 0x0018: /* 24 CAPSETTYPE_WINDOW */
                xrdp_caps_process_window(self, s, len);
                break;
            case 0x001A: /* 26 CAPSETTYPE_MULTIFRAGMENTUPDATE */
                xrdp_caps_process_multifragmentupdate(self, s, len);
                break;
            case RDP_CAPSET_BMPCODECS: /* 0x1d(29) */
                xrdp_caps_process_codecs(self, s, len);
                break;
            case 0x001E: /* CAPSSETTYPE_FRAME_ACKNOWLEDGE */
                xrdp_caps_process_frame_ack(self, s, len);
                break;
            case RDP_CAPSET_SURFCMDS: /* CAPSETTYPE_SURFACE_COMMANDS */
                xrdp_caps_process_surface_cmds(self, s, len);
                break;
            default:
                g_writeln("unknown in xrdp_caps_process_confirm_active %d", type);
                break;
        }

        s->p = p + len + 4;
    }

    if (self->client_info.no_orders_supported &&
        (self->client_info.offscreen_support_level != 0))
    {
        g_writeln("xrdp_caps_process_confirm_active: not enough orders "
                  "supported by client, client wants off screen bitmap but "
                  "offscreen bitmaps disabled");
        self->client_info.offscreen_support_level = 0;
        self->client_info.offscreen_cache_size = 0;
        self->client_info.offscreen_cache_entries = 0;
    }

    DEBUG(("out xrdp_caps_process_confirm_active"));
    return 0;
}
Пример #13
0
/* returns error */
static int APP_CC
file_read_line(struct stream *s, char *text, int text_bytes)
{
    int i;
    int skip_to_end;
    int at_end;
    char c;
    char *hold;

    skip_to_end = 0;

    if (!s_check_rem(s, 1))
    {
        return 1;
    }

    hold = s->p;
    i = 0;
    in_uint8(s, c);

    while (c != 10 && c != 13)
    {
        /* these mean skip the rest of the line */
        if (c == '#' || c == '!' || c == ';')
        {
            skip_to_end = 1;
        }

        if (!skip_to_end)
        {
            text[i] = c;
            i++;
            if (i >= text_bytes)
            {
                return 1;
            }
        }

        if (s_check_rem(s, 1))
        {
            in_uint8(s, c);
        }
        else
        {
            c = 0;
            break;
        }
    }

    if (c == 10 || c == 13)
    {
        at_end = 0;

        while (c == 10 || c == 13)
        {
            if (s_check_rem(s, 1))
            {
                in_uint8(s, c);
            }
            else
            {
                at_end = 1;
                break;
            }
        }

        if (!at_end)
        {
            s->p--;
        }
    }

    text[i] = 0;

    if (text[0] == '[')
    {
        s->p = hold;
        return 1;
    }

    return 0;
}
static void
cliprdr_process(STREAM s)
{
	uint16 type, status;
	uint32 length, format;
	uint8 *data;
	struct stream packet = *s;

	in_uint16_le(s, type);
	in_uint16_le(s, status);
	in_uint32_le(s, length);
	data = s->p;

	DEBUG_CLIPBOARD(("CLIPRDR recv: type=%d, status=%d, length=%d\n", type, status, length));

	if (!s_check_rem(s, length))
	{
		rdp_protocol_error("cliprdr_process(), consume of packet from stream would overrun", &packet);
	}

	if (status == CLIPRDR_ERROR)
	{
		switch (type)
		{
			case CLIPRDR_FORMAT_ACK:
				/* FIXME: We seem to get this when we send an announce while the server is
				   still processing a paste. Try sending another announce. */
				cliprdr_send_native_format_announce(last_formats,
								    last_formats_length);
				break;
			case CLIPRDR_DATA_RESPONSE:
				ui_clip_request_failed();
				break;
			default:
				DEBUG_CLIPBOARD(("CLIPRDR error (type=%d)\n", type));
		}

		return;
	}

	switch (type)
	{
		case CLIPRDR_CONNECT:
			ui_clip_sync();
			break;
		case CLIPRDR_FORMAT_ANNOUNCE:
			ui_clip_format_announce(data, length);
			cliprdr_send_packet(CLIPRDR_FORMAT_ACK, CLIPRDR_RESPONSE, NULL, 0);
			return;
		case CLIPRDR_FORMAT_ACK:
			break;
		case CLIPRDR_DATA_REQUEST:
			in_uint32_le(s, format);
			ui_clip_request_data(format);
			break;
		case CLIPRDR_DATA_RESPONSE:
			ui_clip_handle_data(data, length);
			break;
		case 7:	/* TODO: W2K3 SP1 sends this on connect with a value of 1 */
			break;
		default:
			unimpl("CLIPRDR packet type %d\n", type);
	}
}
Пример #15
0
void
rdpsnd_process_negotiate(STREAM in)
{
	unsigned int in_format_count, i;
	WAVEFORMATEX *format;
	STREAM out;
	BOOL device_available = False;
	int readcnt;
	int discardcnt;

	in_uint8s(in, 14);	/* flags, volume, pitch, UDP port */
	in_uint16_le(in, in_format_count);
	in_uint8s(in, 4);	/* pad, status, pad */

	if (wave_out_open())
	{
		wave_out_close();
		device_available = True;
	}

	format_count = 0;
	if (s_check_rem(in, 18 * in_format_count))
	{
		for (i = 0; i < in_format_count; i++)
		{
			format = &formats[format_count];
			in_uint16_le(in, format->wFormatTag);
			in_uint16_le(in, format->nChannels);
			in_uint32_le(in, format->nSamplesPerSec);
			in_uint32_le(in, format->nAvgBytesPerSec);
			in_uint16_le(in, format->nBlockAlign);
			in_uint16_le(in, format->wBitsPerSample);
			in_uint16_le(in, format->cbSize);

			/* read in the buffer of unknown use */
			readcnt = format->cbSize;
			discardcnt = 0;
			if (format->cbSize > MAX_CBSIZE)
			{
				fprintf(stderr, "cbSize too large for buffer: %d\n",
					format->cbSize);
				readcnt = MAX_CBSIZE;
				discardcnt = format->cbSize - MAX_CBSIZE;
			}
			in_uint8a(in, format->cb, readcnt);
			in_uint8s(in, discardcnt);

			if (device_available && wave_out_format_supported(format))
			{
				format_count++;
				if (format_count == MAX_FORMATS)
					break;
			}
		}
	}

	out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
	out_uint32_le(out, 3);	/* flags */
	out_uint32(out, 0xffffffff);	/* volume */
	out_uint32(out, 0);	/* pitch */
	out_uint16(out, 0);	/* UDP port */

	out_uint16_le(out, format_count);
	out_uint8(out, 0x95);	/* pad? */
	out_uint16_le(out, 2);	/* status */
	out_uint8(out, 0x77);	/* pad? */

	for (i = 0; i < format_count; i++)
	{
		format = &formats[i];
		out_uint16_le(out, format->wFormatTag);
		out_uint16_le(out, format->nChannels);
		out_uint32_le(out, format->nSamplesPerSec);
		out_uint32_le(out, format->nAvgBytesPerSec);
		out_uint16_le(out, format->nBlockAlign);
		out_uint16_le(out, format->wBitsPerSample);
		out_uint16(out, 0);	/* cbSize */
	}

	s_mark_end(out);
	rdpsnd_send(out);
}
Пример #16
0
/* return error */
static int APP_CC
l_file_read_section(int fd, int max_file_size, const char *section,
                    struct list *names, struct list *values)
{
    struct stream *s;
    char *data;
    char *text;
    char *name;
    char *value;
    char *lvalue;
    char c;
    int in_it;
    int in_it_index;
    int len;
    int index;
    int file_size;

    data = (char *) g_malloc(FILE_MAX_LINE_BYTES * 3, 0);
    text = data;
    name = text + FILE_MAX_LINE_BYTES;
    value = name + FILE_MAX_LINE_BYTES;

    file_size = 32 * 1024; /* 32 K file size limit */
    g_file_seek(fd, 0);
    in_it_index = 0;
    in_it = 0;
    g_memset(text, 0, FILE_MAX_LINE_BYTES);
    list_clear(names);
    list_clear(values);
    make_stream(s);
    init_stream(s, file_size);
    len = g_file_read(fd, s->data, file_size);

    if (len > 0)
    {
        s->end = s->p + len;

        for (index = 0; index < len; index++)
        {
            if (!s_check_rem(s, 1))
            {
                break;
            }
            in_uint8(s, c);
            if ((c == '#') || (c == ';'))
            {
                if (file_read_line(s, text, FILE_MAX_LINE_BYTES) != 0)
                {
                    break;
                }
                in_it = 0;
                in_it_index = 0;
                g_memset(text, 0, FILE_MAX_LINE_BYTES);
                continue;
            }
            if (c == '[')
            {
                in_it = 1;
            }
            else if (c == ']')
            {
                if (g_strcasecmp(section, text) == 0)
                {
                    file_read_line(s, text, FILE_MAX_LINE_BYTES);
                    while (file_read_line(s, text, FILE_MAX_LINE_BYTES) == 0)
                    {
                        if (g_strlen(text) > 0)
                        {
                            file_split_name_value(text, name, value);
                            list_add_item(names, (tbus)g_strdup(name));

                            if (value[0] == '$')
                            {
                                lvalue = g_getenv(value + 1);

                                if (lvalue != 0)
                                {
                                    list_add_item(values, (tbus)g_strdup(lvalue));
                                }
                                else
                                {
                                    list_add_item(values, (tbus)g_strdup(""));
                                }
                            }
                            else
                            {
                                list_add_item(values, (tbus)g_strdup(value));
                            }
                        }
                    }

                    free_stream(s);
                    g_free(data);
                    return 0;
                }

                in_it = 0;
                in_it_index = 0;
                g_memset(text, 0, FILE_MAX_LINE_BYTES);
            }
            else if (in_it)
            {
                text[in_it_index] = c;
                in_it_index++;
                if (in_it_index >= FILE_MAX_LINE_BYTES)
                {
                    break;
                }
            }
        }
    }
    free_stream(s);
    g_free(data);
    return 1;
}
Пример #17
0
static void
rdpsnd_process_negotiate(STREAM in)
{
	uint16 in_format_count, i;
	uint8 pad;
	uint16 version;
	RD_WAVEFORMATEX *format;
	STREAM out;
	RD_BOOL device_available = False;
	int readcnt;
	int discardcnt;

	in_uint8s(in, 14);	/* initial bytes not valid from server */
	in_uint16_le(in, in_format_count);
	in_uint8(in, pad);
	in_uint16_le(in, version);
	in_uint8s(in, 1);	/* padding */

	DEBUG_SOUND(("RDPSND: RDPSND_NEGOTIATE(formats: %d, pad: 0x%02x, version: %x)\n",
		     (int) in_format_count, (unsigned) pad, (unsigned) version));

	if (rdpsnd_negotiated)
	{
		error("RDPSND: Extra RDPSND_NEGOTIATE in the middle of a session\n");
		/* Do a complete reset of the sound state */
		rdpsnd_reset_state();
	}

	if (!current_driver && g_rdpsnd)
		device_available = rdpsnd_auto_select();

	if (current_driver && !device_available && current_driver->wave_out_open())
	{
		current_driver->wave_out_close();
		device_available = True;
	}

	format_count = 0;
	if (s_check_rem(in, 18 * in_format_count))
	{
		for (i = 0; i < in_format_count; i++)
		{
			format = &formats[format_count];
			in_uint16_le(in, format->wFormatTag);
			in_uint16_le(in, format->nChannels);
			in_uint32_le(in, format->nSamplesPerSec);
			in_uint32_le(in, format->nAvgBytesPerSec);
			in_uint16_le(in, format->nBlockAlign);
			in_uint16_le(in, format->wBitsPerSample);
			in_uint16_le(in, format->cbSize);

			/* read in the buffer of unknown use */
			readcnt = format->cbSize;
			discardcnt = 0;
			if (format->cbSize > MAX_CBSIZE)
			{
				fprintf(stderr, "cbSize too large for buffer: %d\n",
					format->cbSize);
				readcnt = MAX_CBSIZE;
				discardcnt = format->cbSize - MAX_CBSIZE;
			}
			in_uint8a(in, format->cb, readcnt);
			in_uint8s(in, discardcnt);

			if (current_driver && current_driver->wave_out_format_supported(format))
			{
				format_count++;
				if (format_count == MAX_FORMATS)
					break;
			}
		}
	}

	out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);

	uint32 flags = TSSNDCAPS_VOLUME;

	/* if sound is enabled, set snd caps to alive to enable
	   transmision of audio from server */
	if (g_rdpsnd)
	{
		flags |= TSSNDCAPS_ALIVE;
	}
	out_uint32_le(out, flags);	/* TSSNDCAPS flags */

	out_uint32(out, 0xffffffff);	/* volume */
	out_uint32(out, 0);	/* pitch */
	out_uint16(out, 0);	/* UDP port */

	out_uint16_le(out, format_count);
	out_uint8(out, 0);	/* padding */
	out_uint16_le(out, 2);	/* version */
	out_uint8(out, 0);	/* padding */

	for (i = 0; i < format_count; i++)
	{
		format = &formats[i];
		out_uint16_le(out, format->wFormatTag);
		out_uint16_le(out, format->nChannels);
		out_uint32_le(out, format->nSamplesPerSec);
		out_uint32_le(out, format->nAvgBytesPerSec);
		out_uint16_le(out, format->nBlockAlign);
		out_uint16_le(out, format->wBitsPerSample);
		out_uint16(out, 0);	/* cbSize */
	}

	s_mark_end(out);

	DEBUG_SOUND(("RDPSND: -> RDPSND_NEGOTIATE(formats: %d)\n", (int) format_count));

	rdpsnd_send(out);

	rdpsnd_negotiated = True;
}
Пример #18
0
static void rdpsnd_process_rec_negotiate(STREAM in) {
	uint16 in_format_count, i;
	uint16 version;
	RD_WAVEFORMATEX *format;
	STREAM out;
	RD_BOOL device_available = False;
	int readcnt;
	int discardcnt;

	in_uint8s(in, 8);
	/* initial bytes not valid from server */
	in_uint16_le(in, in_format_count);
	in_uint16_le(in, version);

	DEBUG_SOUND(("RDPSND: RDPSND_REC_NEGOTIATE(formats: %d, version: %x)\n",
					(int) in_format_count, (unsigned) version));

	if (rdpsnd_rec_negotiated) {
		error(
				"RDPSND: Extra RDPSND_REC_NEGOTIATE in the middle of a session\n");
		/* Do a complete reset of the sound state */
		rdpsnd_reset_state();
	}

	if (!current_driver)
		device_available = rdpsnd_auto_select();

	if (current_driver && !device_available && current_driver->wave_in_open
			&& current_driver->wave_in_open()) {
		current_driver->wave_in_close();
		device_available = True;
	}

	rec_format_count = 0;
	if (s_check_rem(in, 18 * in_format_count)) {
		for (i = 0; i < in_format_count; i++) {
			format = &rec_formats[rec_format_count];
			in_uint16_le(in, format->wFormatTag);
			in_uint16_le(in, format->nChannels);
			in_uint32_le(in, format->nSamplesPerSec);
			in_uint32_le(in, format->nAvgBytesPerSec);
			in_uint16_le(in, format->nBlockAlign);
			in_uint16_le(in, format->wBitsPerSample);
			in_uint16_le(in, format->cbSize);

			/* read in the buffer of unknown use */
			readcnt = format->cbSize;
			discardcnt = 0;
			if (format->cbSize > MAX_CBSIZE)
			{
				fprintf(stderr, "cbSize too large for buffer: %d\n",
						format->cbSize);
				readcnt = MAX_CBSIZE;
				discardcnt = format->cbSize - MAX_CBSIZE;
			}in_uint8a(in, format->cb, readcnt);
			in_uint8s(in, discardcnt);

			if (current_driver && current_driver->wave_in_format_supported
					&& current_driver->wave_in_format_supported(format)) {
				rec_format_count++;
				if (rec_format_count == MAX_FORMATS
					)
					break;
			}
		}
	}

	out = rdpsnd_init_packet(RDPSND_REC_NEGOTIATE, 12 + 18 * rec_format_count);
	out_uint32_le(out, 0x00000000);
	/* flags */
	out_uint32_le(out, 0xffffffff);
	/* volume */
	out_uint16_le(out, rec_format_count);
	out_uint16_le(out, 1);
	/* version */

	for (i = 0; i < rec_format_count; i++) {
		format = &rec_formats[i];
		out_uint16_le(out, format->wFormatTag);
		out_uint16_le(out, format->nChannels);
		out_uint32_le(out, format->nSamplesPerSec);
		out_uint32_le(out, format->nAvgBytesPerSec);
		out_uint16_le(out, format->nBlockAlign);
		out_uint16_le(out, format->wBitsPerSample);
		out_uint16(out, 0);
		/* cbSize */
	}

	s_mark_end(out);

	DEBUG_SOUND(("RDPSND: -> RDPSND_REC_NEGOTIATE(formats: %d)\n", (int) rec_format_count));

	rdpsnd_send(out);

	rdpsnd_rec_negotiated = True;
}
Пример #19
0
enum SCP_SERVER_STATES_E
scp_v0s_accept(struct SCP_CONNECTION *c, struct SCP_SESSION **s, int skipVchk)
{
    tui32 version = 0;
    tui32 size;
    struct SCP_SESSION *session = 0;
    tui16 sz;
    tui32 code = 0;
    char buf[257];

    if (!skipVchk)
    {
        LOG_DBG("[v0:%d] starting connection", __LINE__);

        if (0 == scp_tcp_force_recv(c->in_sck, c->in_s->data, 8))
        {
            c->in_s->end = c->in_s->data + 8;
            in_uint32_be(c->in_s, version);

            if (version != 0)
            {
                log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: version error", __LINE__);
                return SCP_SERVER_STATE_VERSION_ERR;
            }
        }
        else
        {
            log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__);
            return SCP_SERVER_STATE_NETWORK_ERR;
        }
    }

    in_uint32_be(c->in_s, size);

    init_stream(c->in_s, 8196);

    if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8))
    {
        log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__);
        return SCP_SERVER_STATE_NETWORK_ERR;
    }

    c->in_s->end = c->in_s->data + (size - 8);

    in_uint16_be(c->in_s, code);

    if (code == 0 || code == 10 || code == 20)
    {
        session = scp_session_create();

        if (0 == session)
        {
            log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__);
            return SCP_SERVER_STATE_INTERNAL_ERR;
        }

        scp_session_set_version(session, version);

        if (code == 0)
        {
            scp_session_set_type(session, SCP_SESSION_TYPE_XVNC);
        }
        else if (code == 10)
        {
            scp_session_set_type(session, SCP_SESSION_TYPE_XRDP);
        }
        else if (code == 20)
        {
            scp_session_set_type(session, SCP_SESSION_TYPE_XORG);
        }

        /* reading username */
        in_uint16_be(c->in_s, sz);
        buf[sz] = '\0';
        in_uint8a(c->in_s, buf, sz);

        if (0 != scp_session_set_username(session, buf))
        {
            scp_session_destroy(session);
            log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting username", __LINE__);
            return SCP_SERVER_STATE_INTERNAL_ERR;
        }

        /* reading password */
        in_uint16_be(c->in_s, sz);
        buf[sz] = '\0';
        in_uint8a(c->in_s, buf, sz);

        if (0 != scp_session_set_password(session, buf))
        {
            scp_session_destroy(session);
            log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting password", __LINE__);
            return SCP_SERVER_STATE_INTERNAL_ERR;
        }

        /* width */
        in_uint16_be(c->in_s, sz);
        scp_session_set_width(session, sz);
        /* height */
        in_uint16_be(c->in_s, sz);
        scp_session_set_height(session, sz);
        /* bpp */
        in_uint16_be(c->in_s, sz);
        scp_session_set_bpp(session, (tui8)sz);

        if (s_check_rem(c->in_s, 2))
        {
            /* reading domain */
            in_uint16_be(c->in_s, sz);

            if (sz > 0)
            {
                in_uint8a(c->in_s, buf, sz);
                buf[sz] = '\0';
                scp_session_set_domain(session, buf);
            }
        }

        if (s_check_rem(c->in_s, 2))
        {
            /* reading program */
            in_uint16_be(c->in_s, sz);

            if (sz > 0)
            {
                in_uint8a(c->in_s, buf, sz);
                buf[sz] = '\0';
                scp_session_set_program(session, buf);
            }
        }

        if (s_check_rem(c->in_s, 2))
        {
            /* reading directory */
            in_uint16_be(c->in_s, sz);

            if (sz > 0)
            {
                in_uint8a(c->in_s, buf, sz);
                buf[sz] = '\0';
                scp_session_set_directory(session, buf);
            }
        }

        if (s_check_rem(c->in_s, 2))
        {
            /* reading client IP address */
            in_uint16_be(c->in_s, sz);

            if (sz > 0)
            {
                in_uint8a(c->in_s, buf, sz);
                buf[sz] = '\0';
                scp_session_set_client_ip(session, buf);
            }
        }
    }
    else if (code == SCP_GW_AUTHENTICATION)
    {
        /* g_writeln("Command is SCP_GW_AUTHENTICATION"); */
        session = scp_session_create();

        if (0 == session)
        {
            /* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error",      __LINE__);*/
            return SCP_SERVER_STATE_INTERNAL_ERR;
        }

        scp_session_set_version(session, version);
        scp_session_set_type(session, SCP_GW_AUTHENTICATION);
        /* reading username */
        in_uint16_be(c->in_s, sz);
        buf[sz] = '\0';
        in_uint8a(c->in_s, buf, sz);

        /* g_writeln("Received user name: %s",buf); */
        if (0 != scp_session_set_username(session, buf))
        {
            scp_session_destroy(session);
            /* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting        username", __LINE__);*/
            return SCP_SERVER_STATE_INTERNAL_ERR;
        }

        /* reading password */
        in_uint16_be(c->in_s, sz);
        buf[sz] = '\0';
        in_uint8a(c->in_s, buf, sz);

        /* g_writeln("Received password: %s",buf); */
        if (0 != scp_session_set_password(session, buf))
        {
            scp_session_destroy(session);
            /* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting password", __LINE__); */
            return SCP_SERVER_STATE_INTERNAL_ERR;
        }
    }
    else
    {
        log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: sequence error", __LINE__);
        return SCP_SERVER_STATE_SEQUENCE_ERR;
    }

    (*s) = session;
    return SCP_SERVER_STATE_OK;
}
Пример #20
0
/* return error */
static int l_file_read_section(int fd, int max_file_size, const char *section, xrdpList *names, xrdpList *values)
{
	struct stream *s;
	char text[512];
	char name[512];
	char value[512];
	char *lvalue;
	char c;
	int in_it;
	int in_it_index;
	int len;
	int index;
	int file_size;

	file_size = 32 * 1024; /* 32 K file size limit */
	g_file_seek(fd, 0);
	in_it_index = 0;
	in_it = 0;
	g_memset(text, 0, 512);
	list_clear(names);
	list_clear(values);
	make_stream(s);
	init_stream(s, file_size);
	len = g_file_read(fd, s->data, file_size);

	if (len > 0)
	{
		s->end = s->p + len;

		for (index = 0; index < len; index++)
		{
			if (!s_check_rem(s, 1))
			{
				break;
			}

			in_uint8(s, c);

			if ((c == '#') || (c == ';'))
			{
				file_read_line(s, text);
				in_it = 0;
				in_it_index = 0;
				g_memset(text, 0, 512);
				continue;
			}

			if (c == '[')
			{
				in_it = 1;
			}
			else if (c == ']')
			{
				if (g_strcasecmp(section, text) == 0)
				{
					file_read_line(s, text);

					while (file_read_line(s, text) == 0)
					{
						if (g_strlen(text) > 0)
						{
							file_split_name_value(text, name, value);
							list_add_item(names, (tbus) g_strdup(name));

							if (value[0] == '$')
							{
								lvalue = g_getenv(value + 1);

								if (lvalue != 0)
								{
									list_add_item(values, (tbus) g_strdup(lvalue));
								}
								else
								{
									list_add_item(values, (tbus) g_strdup(""));
								}
							}
							else
							{
								list_add_item(values, (tbus) g_strdup(value));
							}
						}
					}

					free_stream(s);
					return 0;
				}

				in_it = 0;
				in_it_index = 0;
				g_memset(text, 0, 512);
			}
			else if (in_it)
			{
				text[in_it_index] = c;
				in_it_index++;
			}
		}
	}

	free_stream(s);
	return 1;
}
Пример #21
0
/* Establish a connection up to the ISO layer */
RD_BOOL
iso_connect(char *server, char *username, char *domain, char *password,
	    RD_BOOL reconnect, uint32 * selected_protocol)
{
	STREAM s;
	uint8 code;
	uint32 neg_proto;

	g_negotiate_rdp_protocol = True;

	neg_proto = PROTOCOL_SSL;

#ifdef WITH_CREDSSP
	if (!g_use_password_as_pin)
		neg_proto |= PROTOCOL_HYBRID;
	else if (g_sc_csp_name || g_sc_reader_name || g_sc_card_name || g_sc_container_name)
		neg_proto |= PROTOCOL_HYBRID;
	else
		warning("Disables CredSSP due to missing smartcard information for SSO.\n");
#endif

      retry:
	*selected_protocol = PROTOCOL_RDP;
	code = 0;

	if (!tcp_connect(server))
		return False;

	iso_send_connection_request(username, neg_proto);

	s = iso_recv_msg(&code, NULL);
	if (s == NULL)
		return False;

	if (code != ISO_PDU_CC)
	{
		error("expected CC, got 0x%x\n", code);
		tcp_disconnect();
		return False;
	}

	if (g_rdp_version >= RDP_V5 && s_check_rem(s, 8))
	{
		/* handle RDP_NEG_REQ response */
		const char *reason = NULL;

		uint8 type = 0, flags = 0;
		uint16 length = 0;
		uint32 data = 0;

		in_uint8(s, type);
		in_uint8(s, flags);
		in_uint16(s, length);
		in_uint32(s, data);

		if (type == RDP_NEG_FAILURE)
		{
			RD_BOOL retry_without_neg = False;

			switch (data)
			{
				case SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER:
					reason = "SSL with user authentication required by server";
					break;
				case SSL_NOT_ALLOWED_BY_SERVER:
					reason = "SSL not allowed by server";
					retry_without_neg = True;
					break;
				case SSL_CERT_NOT_ON_SERVER:
					reason = "no valid authentication certificate on server";
					retry_without_neg = True;
					break;
				case INCONSISTENT_FLAGS:
					reason = "inconsistent negotiation flags";
					break;
				case SSL_REQUIRED_BY_SERVER:
					reason = "SSL required by server";
					break;
				case HYBRID_REQUIRED_BY_SERVER:
					reason = "CredSSP required by server";
					break;
				default:
					reason = "unknown reason";
			}

			tcp_disconnect();

			if (retry_without_neg)
			{
				fprintf(stderr,
					"Failed to negotiate protocol, retrying with plain RDP.\n");
				g_negotiate_rdp_protocol = False;
				goto retry;
			}

			fprintf(stderr, "Failed to connect, %s.\n", reason);
			return False;
		}

		if (type != RDP_NEG_RSP)
		{
			tcp_disconnect();
			error("Expected RDP_NEG_RSP, got type = 0x%x\n", type);
			return False;
		}

		/* handle negotiation response */
		if (data == PROTOCOL_SSL)
		{
			if (!tcp_tls_connect())
			{
				/* failed to connect using cssp, let retry with plain TLS */
				tcp_disconnect();
				neg_proto = PROTOCOL_RDP;
				goto retry;
			}
			/* do not use encryption when using TLS */
			g_encryption = False;
			fprintf(stderr, "Connection established using SSL.\n");
		}
#ifdef WITH_CREDSSP
		else if (data == PROTOCOL_HYBRID)
		{
			if (!cssp_connect(server, username, domain, password, s))
			{
				/* failed to connect using cssp, let retry with plain TLS */
				tcp_disconnect();
				neg_proto = PROTOCOL_SSL;
				goto retry;
			}

			/* do not use encryption when using TLS */
			fprintf(stderr, "Connection established using CredSSP.\n");
			g_encryption = False;
		}
#endif
		else if (data == PROTOCOL_RDP)
		{
			fprintf(stderr, "Connection established using plain RDP.\n");
		}
		else if (data != PROTOCOL_RDP)
		{
			tcp_disconnect();
			error("Unexpected protocol in negotiation response, got data = 0x%x.\n",
			      data);
			return False;
		}

		*selected_protocol = data;
	}
	return True;
}
Пример #22
0
static int file_read_line(struct stream *s, char *text)
{
	int i;
	int skip_to_end;
	int at_end;
	char c;
	char *hold;

	skip_to_end = 0;

	if (!s_check_rem(s, 1))
	{
		return 1;
	}

	hold = s->p;
	i = 0;
	in_uint8(s, c);

	while (c != 10 && c != 13)
	{
		if (c == '#' || c == '!' || c == ';')
		{
			skip_to_end = 1;
		}

		if (!skip_to_end)
		{
			text[i] = c;
			i++;
		}

		if (s_check_rem(s, 1))
		{
			in_uint8(s, c);
		}
		else
		{
			c = 0;
			break;
		}
	}

	if (c == 10 || c == 13)
	{
		at_end = 0;

		while (c == 10 || c == 13)
		{
			if (s_check_rem(s, 1))
			{
				in_uint8(s, c);
			}
			else
			{
				at_end = 1;
				break;
			}
		}

		if (!at_end)
		{
			s->p--;
		}
	}

	text[i] = 0;

	if (text[0] == '[')
	{
		s->p = hold;
		return 1;
	}

	return 0;
}
Пример #23
0
int
xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
{
    int cap_len;
    int source_len;
    int num_caps;
    int index;
    int type;
    int len;
    char *p;

    DEBUG(("in xrdp_caps_process_confirm_active"));
    in_uint8s(s, 4); /* rdp_shareid */
    in_uint8s(s, 2); /* userid */
    in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */
    in_uint16_le(s, cap_len);
    in_uint8s(s, source_len);
    in_uint16_le(s, num_caps);
    in_uint8s(s, 2); /* pad */

    if ((cap_len < 0) || (cap_len > 1024 * 1024))
    {
        return 1;
    }

    for (index = 0; index < num_caps; index++)
    {
        p = s->p;
        if (!s_check_rem(s, 4))
        {
            g_writeln("xrdp_caps_process_confirm_active: error 1");
            return 1;
        }
        in_uint16_le(s, type);
        in_uint16_le(s, len);
        if ((len < 4) || !s_check_rem(s, len - 4))
        {
            g_writeln("xrdp_caps_process_confirm_active: error: len %d, "
                      "remaining %d", len, (int) (s->end - s->p));
            return 1;
        }
        len -= 4;
        switch (type)
        {
            case CAPSTYPE_GENERAL:
                DEBUG(("CAPSTYPE_GENERAL"));
                xrdp_caps_process_general(self, s, len);
                break;
            case CAPSTYPE_BITMAP:
                DEBUG(("CAPSTYPE_BITMAP"));
                break;
            case CAPSTYPE_ORDER:
                DEBUG(("CAPSTYPE_ORDER"));
                xrdp_caps_process_order(self, s, len);
                break;
            case CAPSTYPE_BITMAPCACHE:
                DEBUG(("CAPSTYPE_BMPCACHE"));
                xrdp_caps_process_bmpcache(self, s, len);
                break;
            case CAPSTYPE_CONTROL:
                DEBUG(("CAPSTYPE_CONTROL"));
                break;
            case 6:
                xrdp_caps_process_cache_v3_codec_id(self, s, len);
                break;
            case CAPSTYPE_ACTIVATION:
                DEBUG(("CAPSTYPE_ACTIVAION"));
                break;
            case CAPSTYPE_POINTER:
                DEBUG(("CAPSTYPE_POINTER"));
                xrdp_caps_process_pointer(self, s, len);
                break;
            case CAPSTYPE_SHARE:
                DEBUG(("CAPSTYPE_SHARE"));
                break;
            case CAPSTYPE_COLORCACHE:
                DEBUG(("CAPSTYPE_COLORCACHE"));
                break;
            case CAPSTYPE_SOUND:
                DEBUG(("CAPSTYPE_SOUND"));
                break;
            case CAPSTYPE_INPUT:
                xrdp_caps_process_input(self, s, len);
                break;
            case CAPSTYPE_FONT:
                DEBUG(("CAPSTYPE_FONT"));
                break;
            case CAPSTYPE_BRUSH:
                xrdp_caps_process_brushcache(self, s, len);
                break;
            case CAPSTYPE_GLYPHCACHE:
                DEBUG(("CAPSTYPE_GLYPHCACHE"));
                xrdp_caps_process_glyphcache(self, s, len);
                break;
            case CAPSTYPE_OFFSCREENCACHE:
                DEBUG(("CAPSTYPE_OFFSCREENCACHE"));
                xrdp_caps_process_offscreen_bmpcache(self, s, len);
                break;
            case CAPSTYPE_BITMAPCACHE_REV2:
                DEBUG(("CAPSTYPE_BITMAPCACHE_REV2"));
                xrdp_caps_process_bmpcache2(self, s, len);
                break;
            case CAPSTYPE_VIRTUALCHANNEL:
                DEBUG(("CAPSTYPE_VIRTUALCHANNEL"));
                break;
            case CAPSTYPE_DRAWNINGRIDCACHE:
                DEBUG(("CAPSTYPE_DRAWNINGRIDCACHE"));
                break;
            case CAPSTYPE_DRAWGDIPLUS:
                DEBUG(("CAPSTYPE_DRAWGDIPLUS"));
                break;
            case CAPSTYPE_RAIL:
                xrdp_caps_process_rail(self, s, len);
                break;
            case CAPSTYPE_WINDOW:
                xrdp_caps_process_window(self, s, len);
                break;
            case CAPSSETTYPE_MULTIFRAGMENTUPDATE:
                xrdp_caps_process_multifragmentupdate(self, s, len);
                break;
            case CAPSETTYPE_SURFACE_COMMANDS:
                xrdp_caps_process_surface_cmds(self, s, len);
                break;
            case CAPSSETTYPE_BITMAP_CODECS:
                xrdp_caps_process_codecs(self, s, len);
                break;
            case CAPSTYPE_FRAME_ACKNOWLEDGE:
                xrdp_caps_process_frame_ack(self, s, len);
                break;
            default:
                g_writeln("unknown in xrdp_caps_process_confirm_active %d", type);
                break;
        }

        s->p = p + len + 4;
    }

    if (self->client_info.no_orders_supported &&
        (self->client_info.offscreen_support_level != 0))
    {
        g_writeln("xrdp_caps_process_confirm_active: not enough orders "
                  "supported by client, client wants off screen bitmap but "
                  "offscreen bitmaps disabled");
        self->client_info.offscreen_support_level = 0;
        self->client_info.offscreen_cache_size = 0;
        self->client_info.offscreen_cache_entries = 0;
    }

    DEBUG(("out xrdp_caps_process_confirm_active"));
    return 0;
}