Skip to content
This repository has been archived by the owner on Aug 15, 2022. It is now read-only.

[wiki] Basic Authentication possible fix #362

Closed
eusebiu opened this issue May 10, 2020 · 6 comments
Closed

[wiki] Basic Authentication possible fix #362

eusebiu opened this issue May 10, 2020 · 6 comments

Comments

@eusebiu
Copy link

eusebiu commented May 10, 2020

Version Number and Operating System(s):

master; Windows

Expected behavior:

Get the correct data set from client.

Actual behavior:

Exception in response.GetByteArray()

Steps to reproduce:

  1. create a client authenticator to send the data to server; set it before Connect()
public void AcceptChallenge(NetWorker networker, BMSByte challenge, Action<BMSByte> authServerAction, Action rejectServerAction)
{
	var data = ObjectMapper.BMSByte(0, Encoding.UTF8.GetBytes($"test:test"));

	authServerAction(data);
}
  1. create a server authenticator to read the data
public void VerifyResponse(NetWorker networker, NetworkingPlayer player, BMSByte response, Action<NetworkingPlayer> authUserAction, Action<NetworkingPlayer> rejectUserAction)
{
	ulong steamid = response.GetBasicType<ulong>();
	byte[] ticketBinary = response.GetByteArray(response.StartIndex()); // here exception

	if (AuthUser(steamid, ticketBinary))
	{
		authUserAction(player);
	}
	else
	{
		rejectUserAction(player);
	}
}

Possible fix of VerifyResponse:

if (response == null || response.byteArr == null || 
	response.byteArr.Length == 0 || response.Size == 0)
{
	rejectUserAction(player);
	return;
}

ulong steamid = response.GetBasicType<ulong>();

byte[] ticketBinary = new byte[response.Size];
Buffer.BlockCopy(response.byteArr, response.StartIndex(), ticketBinary, 0, ticketBinary.Length);
@phalasz
Copy link
Contributor

phalasz commented Aug 10, 2020

First thing I noticed is you map a 0 then in verify response you try and get out a ulong. 0 != 0ul when you are mapping it out as the first would map to 4 bytes while a ulong would map to 8 bytes.

Your problem was that your first call to get the id read more data then the internall array had. It also moved the start pointer. Your next call was instructing it to get data from an already moved start pointer that was pointing out of range for the internal array hence the exception.

So your example code should be written like this:

public void AcceptChallenge(
    NetWorker networker,
    BMSByte challenge,
    Action<BMSByte> authServerAction,
    Action rejectServerAction
) {
    ulong steamId = yourMethodThatGetsThis();
    var data = ObjectMapper.BMSByte(steamId, Encoding.UTF8.GetBytes($"test:test"));

    authServerAction(data);
}

Then on the server:

public void VerifyResponse(
    NetWorker networker,
    NetworkingPlayer player,
    BMSByte response,
    Action<NetworkingPlayer> authUserAction,
    Action<NetworkingPlayer> rejectUserAction
) {
	ulong steamid = response.GetBasicType<ulong>();  // <--- Moves internal array pointer.
	byte[] ticketBinary = response.GetBasicType<byte[]>();

	if (AuthUser(steamid, ticketBinary))
	{
		authUserAction(player);
	}
	else
	{
		rejectUserAction(player);
	}
}

@eusebiu
Copy link
Author

eusebiu commented Aug 11, 2020

You are correct but:

If I change as you mention, I now get an OutOfMemoryException: response.GetBasicType<byte[]>() => at x = GetBasicType(StartIndex(), true); // x gets a huge value

If I remove the steamid completely from client and server (since I do not use it), the data sent is not correctly retrieved (in my case it is an encrypted text and decryption does not recognize it).

So, there is an issue of 4 bytes somewhere...

@phalasz
Copy link
Contributor

phalasz commented Aug 11, 2020

That is weird. Haven't seen that before and I have used byte[]s multiple times.

Just an fyi you should not touch byteArr as that is the internal array that might not be what you expect it to be. You can get out the correct byte[] by using CompressBytes()

@eusebiu
Copy link
Author

eusebiu commented Aug 11, 2020

So, if I do this on the client side:

var data = ObjectMapper.BMSByte(Encoding.UTF8.GetBytes($"test:test"));
authServerAction(data);

and
byte[] ticketBinary = response.CompressBytes();
on server side, the data is not correctly retrieved...

image

@phalasz
Copy link
Contributor

phalasz commented Aug 11, 2020

Yes you are seeing the meta data in front. The first 4 bytes is the number of elements as an int of your byte array that you mapped in. Then you have the 9 elements.

Please use byte[] ticketBinary = response.GetBasicType<byte[]>();

You could just map the string instead of the byte array though.

@eusebiu
Copy link
Author

eusebiu commented Aug 11, 2020

Mapping the string directly worked. Thanks! :)

@eusebiu eusebiu closed this as completed Aug 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants