C# max length of URL - c#

I have a huge problem. I write small servers in C#. My clients are JavaScript. JavaScript use HTTP GET to communicate because JavaScript must pass Same Origin Policy. It means I must use HTTP GET to comunication. Now I notice that C# cut (??) my URL.
I sended:
http://172.16.210.25:8000/?callback=ProxyApi.saveStat&cid=1343823765156_495&cidget=null&s[901]=1044!:!5878849%3B6658291%3B2964823%3B1178767%3B469747%3B481939%3B6431323%3B1032649%3B2750603%3B208057%3B9192763%3B6669071%3B2014351%3B6816157%3B3784367%3B1242929%3B4488073%3B7662331%3B2991731%3B6404357%3B8248091%3B1795603%3B4880191%3B3080303%3B4093847%3B4618063%3B7501937%3B2842849%3B6953249%3B7102679%3B5667853%3B9851873%3B5517823%3B6114539%3B6061597%3B7647599%3B4871873%3B400087%3B7514713%3B3958217%3B8163713%3B9560437%3B8229701%3B3408749%3B4432097%3B3353219%3B2936693%3B1343597%3B3490451%3B1266191%3B9125747%3B6152921%3B2689537%3B3796861%3B4987009%3B1206841%3B9278119%3B9499619%3B455627%3B6217051%3B7603201%3B8019079%3B5306033%3B8314939%3B2997221%3B3996221%3B3889649%3B1148507%3B9397139%3B4984949%3B6576473%3B3993247%3B676051%3B5%3B&s[902]=929!:!9012569%3B9836633%3B5239051%3B6102559%3B5944079%3B9749681%3B4007797%3B344821%3B9914917%3B1950227%3B982847%3B6610337%3B6734281%3B4213463%3B1620449%3B1745111%3B8005717%3B6740443%3B8290811%3B9652289%3B279557%3B9077213%3B169933%3B4785463%3B368521%3B5881487%3B5735711%3B189377%3B3417091%3B8616299%3B7168723%3B4220969%3B4493651%3B5067977%3B1646387%3B3925297%3B5990723%3B6826471%3B3040753%3B1449733%3B8905681%3B2502001%3B7304107%3B1022677%3B4966529%3B8679397%3B4319519%3B3991279%3B1128641%3B2148631%3B2215987%3B1135217%3B3846281%3B1049843%3B309937%3B2241691%3B8768581%3B6199693%3B7973921%3B9683627%3B9664957%3B4493023%3B2494729%3B3581167%3B8474597%3B1987919%3B6099271%3B&t=68999&pxid=142221422
But I got in string:
?callback=ProxyApi.saveStat&cid=1343823765156_495&cidget=null&s[901]=1044!:!5878849%3B6658291%3B2964823%3B1178767%3B469747%3B481939%3B6431323%3B1032649%3B2750603%3B208057%3B9192763%3B6669071%3B2014351%3B6816157%3B3784367%3B1242929%3B4488073%3B7662331%3B2991731%3B6404357%3B8248091%3B1795603%3B4880191%3B3080303%3B4093847%3B4618063%3B7501937%3B2842849%3B6953249%3B7102679%3B5667853%3B9851873%3B5517823%3B6114539%3B6061597%3B7647599%3B4871873%3B400087%3B7514713%3B3958217%3B8163713%3B9560437%3B8229701%3B3408749%3B4432097%3B3353219%3B2936693%3B1343597%3B3490451%3B1266191%3B9125747%3B6152921%3B2689537%3B3796861%3B4987009%3B1206841%3B9278119%3B9499619%3B455627%3B6217051%3B7603201%3B8019079%3B5306033%3B8314939%3B2997221%3B3996221%3B3889649%3B1148507%3B9397139%3B4984949%3B6576473%3B3993247%3B676051%3B5%3B&s[902]=929!:!9012569%3B9836633%3B5239051%3B6102559%3B5944079%3B9749681%3B4007797%3B344821%3B9914917%3B1950227%3B982847%3B6610337%3B6734281%3B4213463%3B1620449%3B1745111%3B8005717%3B6740443%3B8290811%3B9652289%3B279
I lost some important data.
Im listing using:
IPAddress local_ip = Dns.GetHostAddresses(Dns.GetHostName())[0];
TcpListener sockServer = new TcpListener(local_ip,Port);
sockServer.Start();
And
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadFunction), sockServer.AcceptSocket());
And inside ThreadFunction I have
static void ThreadFunction(Object param)
{
Socket socket = (Socket)param;
proxy.Run(socket);
}
Finally I read message using this:
int bytes = ReadMessage(socket, readBuf, ref strFromClient);
Can you help me pass problem with URL LENGHT or change method of listining (unknown Javscript clients send large messeage using HTTP GET.)
===================
EDIT
I try using IE, Chrome and FF. I sent
http://172.16.210.25:8000/?callback=ProxyApi.saveStat&cid=1343823765156_495&cidget=null&s[901]=1044!:!5878849%3B6658291%3B2964823%3B1178767%3B469747%3B481939%3B6431323%3B1032649%3B2750603%3B208057%3B9192763%3B6669071%3B2014351%3B6816157%3B3784367%3B1242929%3B4488073%3B7662331%3B2991731%3B6404357%3B8248091%3B1795603%3B4880191%3B3080303%3B4093847%3B4618063%3B7501937%3B2842849%3B6953249%3B7102679%3B5667853%3B9851873%3B5517823%3B6114539%3B6061597%3B7647599%3B4871873%3B400087%3B7514713%3B3958217%3B8163713%3B9560437%3B8229701%3B3408749%3B4432097%3B3353219%3B2936693%3B1343597%3B3490451%3B1266191%3B9125747%3B6152921%3B2689537%3B3796861%3B4987009%3B1206841%3B9278119%3B9499619%3B455627%3B6217051%3B7603201%3B8019079%3B5306033%3B8314939%3B2997221%3B3996221%3B3889649%3B1148507%3B9397139%3B4984949%3B6576473%3B3993247%3B676051%3B5%3B&s[902]=929!:!9012569%3B9836633%3B5239051%3B6102559%3B5944079%3B9749681%3B4007797%3B344821%3B9914917%3B1950227%3B982847%3B6610337%3B6734281%3B4213463%3B1620449%3B1745111%3B8005717%3B6740443%3B8290811%3B9652289%3B279557%3B9077213%3B169933%3B4785463%3B368521%3B5881487%3B5735711%3B189377%3B3417091%3B8616299%3B7168723%3B4220969%3B4493651%3B5067977%3B1646387%3B3925297%3B5990723%3B6826471%3B3040753%3B1449733%3B8905681%3B2502001%3B7304107%3B1022677%3B4966529%3B8679397%3B4319519%3B3991279%3B1128641%3B2148631%3B2215987%3B1135217%3B3846281%3B1049843%3B309937%3B2241691%3B8768581%3B6199693%3B7973921%3B9683627%3B9664957%3B4493023%3B2494729%3B3581167%3B8474597%3B1987919%3B6099271%3B&t=68999&pxid=142221422
But I always get
GET /?callback=ProxyApi.saveStat&cid=1343823765156_495&cidget=null&s[901]=1044!:!5878849%3B6658291%3B2964823%3B1178767%3B469747%3B481939%3B6431323%3B1032649%3B2750603%3B208057%3B9192763%3B6669071%3B2014351%3B6816157%3B3784367%3B1242929%3B4488073%3B7662331%3B2991731%3B6404357%3B8248091%3B1795603%3B4880191%3B3080303%3B4093847%3B4618063%3B7501937%3B2842849%3B6953249%3B7102679%3B5667853%3B9851873%3B5517823%3B6114539%3B6061597%3B7647599%3B4871873%3B400087%3B7514713%3B3958217%3B8163713%3B9560437%3B8229701%3B3408749%3B4432097%3B3353219%3B2936693%3B1343597%3B3490451%3B1266191%3B9125747%3B6152921%3B2689537%3B3796861%3B4987009%3B1206841%3B9278119%3B9499619%3B455627%3B6217051%3B7603201%3B8019079%3B5306033%3B8314939%3B2997221%3B3996221%3B3889649%3B1148507%3B9397139%3B4984949%3B6576473%3B3993247%3B676051%3B5%3B&s[902]=929!:!9012569%3B9836633%3B5239051%3B6102559%3B5944079%3B9749681%3B4007797%3B344821%3B9914917%3B1950227%3B982847%3B6610337%3B6734281%3B4213463%3B1620449%3B1745111%3B8005717%3B6740443%3B8290811%3B9652289%3B279
Look
private Byte[] readBuf = new Byte[2048];
int bytes = ReadMessage(socket, readBuf, ref strFromClient);
My bytes always are to 1024. Where can be limits of there?

HTTP GET requests are usually limited to ~2000 characters (client-wise, that is)
Here's a reference from MS
GET is not intended for sending large amount of data, that's why it's called GET... try to provide more information regarding your client and we might be able to offer you an alternative

I was careless.
Function ReadMessage is function from own class. And it wrote:
sock.Receive(buf, 1024, 0);
Of course I fix:
sock.Receive(buf,buf.Length,0);
And Now it runs.
Thank for your answers.

Related

Server-Side Request Forgery Fortify Fix

I'm trying to call a webservice. This webservice call depends on the user input as the URL.
The URL looks like follows:
https://someurl.com/somefunction/{userinput}
And my function looks like this
public async Task<Data> GetData(string input)
{
try
{
Address = BaseAddress; // https://someurl.com/somefunction/{userinput}
Address = Address.Replace("{userinput}", input);
....
WebService ws = await base.GetData(httpClient, serverIPaddress);
....
}
}
And I get the security error from Fortify
Server-Side Request Forgery (Input Validation and Representation, Data
Flow)
The function GetAsync() on line 122 initiates a network connection to
a third-party system using user-controlled data for resource URI. An
attacker may leverage this vulnerability to send a request on behalf
of the application server since the request will originate from the
application server's internal IP address.
Here are the recommendations:
Recommendations:
Do not establish network connections based on user-controlled data and
ensure that the request is being sent to the expected destination. If
user data is necessary to build the destination URI, use a level of
indirection: create a list of legitimate resource names that a user is
allowed to specify, and only allow the user to select from the list.
With this approach the input provided by the user is never used
directly to specify the resource name.
In some situations this approach is impractical because the set of
legitimate resource names is too large or too hard to keep track of.
Programmers often resort to blacklisting in these situations.
Blacklisting selectively rejects or escapes potentially dangerous
characters before using the input. However, any such list of unsafe
characters is likely to be incomplete and will almost certainly become
out of date. A better approach is to create a whitelist of characters
that are allowed to appear in the resource name and accept input
composed exclusively of characters in the approved set.
Also, if required, make sure that the user input is only used to
specify a resource on the target system but that the URI scheme, host,
and port is controlled by the application. This way the damage that an
attacker is able to do will be significantly reduced.
But the thing is that I really need to change {userinput} based on the supplied data from user. {userinput} will be a string with a certain maximum length.
How to resolve this issue?
After so much research and hit and try attempts, I finally got this working by appending the input in the BaseAddress
The sample code looks like
public async Task<Data> GetData(string input)
{
try
{
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri($"https://someurl.com/somefunction/{input}");
var content = await httpClient.GetStringAsync("");
return JsonConvert.DeserializeObject<Data>(content);
}
}

RangeFileContentResult and Video streaming with Ranged Requests

I have an application which intended to stream videos back from our local DB. I spent a lot of time yesterday attempting to return the data a either a RangeFileContentResult or RangeFileStreamResult without success.
In short, when I return the file as either of these two results I cannot seem to get a video to stream correctly (or play at all).
The request from the browser gets sent with the following headers:
Range: bytes=0-
And the response comes provided gives these headers as an example:
Accept-Ranges: bytes
Content-Range: bytes 0-5103295/5103296
In terms of network traffic, I get a series of 206's for partial results, then a 200 at the end (according to fiddler) which seems correct.
Chrome's network tab disagrees with this and see's an initial request (always 13 bytes which I assume is a handshake) then a couple more requests which have a status of either cancelled or pending.
As far as I understand, this is more or less correct, 206 - cancel, 206 - cancel etc. But the video never plays.
If I switch the result from my controller to a FileResult, the video plays and Chrome, IE10 and Firefox and appears to begin playing before the end of the download is completed (which feels a little like it's streaming! although I suspect it's not)
But with the range result I get nothing in chrome or IE and the entire video downloads in one drop in firefox.
As far as I understood, the RangeFileContentResult should handle responding to the client with a range of bytes to download (which mine doesn't seem to do, it just tells it to get the whole file (illustrated by the response above)). And the client should respond to that, which it doesn't seem to do.
Does anyone have any thoughts in this area? Specifically:
a) Should RangeFileContentResult be sending a range of bytes back to the client?
b) Is there any way I can explicitly control the range of bytes requested from the client side?
c) Is there any reason or anything I'm doing wrong here which would cause browsers not to load the video at all, when requesting a RangeFileContentResult?
EDIT: Added a diagram to help describe what I'm seeing:
EDIT2: Ok, so the plot thickens. Whilst playing around with the RangedFile gubbins we needed to push another system test version out and I left the 'RangeFileContentResult' on my controller action as below:
private ActionResult RetrieveVideo(MediaItem media)
{
return new RangeFileContentResult(
media.Content,
media.MimeType,
media.Id.ToString(),
DateTime.Now);
}
Rather oddly, this now seems to work as expected on our Azure system test environment but still not on my local machine. I wonder if there's something IIS based which works happily on Azures IIS8, but not on my local 7.5 instance?
The reason of the issue described here is the value passed to modificationDate parameter of RangeFileContentResult constructor:
return new RangeFileContentResult(media.Content, media.MimeType, media.Id.ToString(), DateTime.Now);
This date is used by the RangeFileResult in order to create two headers:
ETag - This header is an identifier used by browser and server to make sure that they are speaking about the same entity.
Last-Modified - This header informs the browser about the last modification date of the entity.
The fact that a DateTime.Now is being passed every time the browser makes partial request might be a reason for ETag and Last-Modified headers values to change before the client will get the whole entity (usually if the entire process takes longer than one second).
In case described above, the browser is sending If-Range header with the request. This header is telling the server that the entire entity should be resend if the entity tag (or modification date because If-Range can carry either one of those two values) doesn't much. This is what happens in this case.
The fact that modification date is "dynamic" may also cause further issues if client decides to use one of following headers for verification: If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match.
The solution in this situation is to keep a modification date in database with the file to make sure it is consistent.
There is also a place for optimization here. Instead of grabbing the whole video from DB every time a partial request is being made, one can either cache it or grab only the relevant part (if the database engine which application is using allows such an operation). Such a mechanism can be used in order to create specialized action result by delivering from RangeFileResult and overwriting WriteEntireEntity and WriteEntityRange methods.
Ok So I didn't have enough time to look at RangeFileResult in details, but I have just downloaded the file (RangeFileContentResult) from
RangeFileContentResult
and modified my code so it looks like
public ActionResult Movie()
{
byte[] file = System.IO.File.ReadAllBytes(#"C:\HOME\asp\Java\Java EE. Programming Spring 3.0\01.avi");
return new RangeFileContentResult(file, "video/x-msvideo", "01.avi", DateTime.Now);
}
and again it works. However, I noticed that when I stop the video I have an exception and it happens in RangeFileResult
if (context.HttpContext.Response.IsClientConnected)
{
WriteEntityRange(context.HttpContext.Response, RangesStartIndexes[i], RangesEndIndexes[i]);
if (MultipartRequest)
context.HttpContext.Response.Write("\r\n");
context.HttpContext.Response.Flush();
}
So you better modify the code to handle it.In terms when users already disconnected , but you are still trying to send them a response.
Again, technically it's not a big difference whether you pass byte[] or Stream , because even when you pass Stream the code working with it
using (FileStream)
{
FileStream.Seek(rangeStartIndex, SeekOrigin.Begin);
int bytesRemaining = Convert.ToInt32(rangeEndIndex - rangeStartIndex) + 1;
byte[] buffer = new byte[_bufferSize];
while (bytesRemaining > 0)
{
int bytesRead = FileStream.Read(buffer, 0, _bufferSize < bytesRemaining ? _bufferSize : bytesRemaining);
response.OutputStream.Write(buffer, 0, bytesRead);
bytesRemaining -= bytesRead;
}
}
again reads data and puts them into an byte[] array!.... So it's up to you!
BUT... I suggest that you pay attention to a content type that you provide!!!
Point is that your browser must be able to handle it!So if you provide something unknown definitely you will have problems.To find your content type string please check
mime-types-by-content-type
Again I just gave a quick look and if you have problems I will help you later when come home.
mofiPlease just copy these two files in your mvc project
RangeFileResult
RangeFileStreamResult
public ActionResult Movie()
{
var path = new FileStream(#"C:\temp\01.avi", FileMode.Open);
return new RangeFileStreamResult(path, "video/x-msvideo", "01.avi", DateTime.Now);
}
Now run your project and open in chrome (for example: http://youraddress.com:45454/Main/Movie) you should see your file playing using a standard chrome video player. it's streaming and you can see it if you put a breakpoint at
return new RangeFileStreamResult(path, "video/x-msvideo", "01.avi", DateTime.Now);
Again the source is easy to modify to change the buffer size which is used for streaming!

C# - Server-side password protection

I am writing two console applications, a client and a server.
I'm a little stuck at two things, which seemed rather easy at first..
#1: I want to write a function for the following piece of code, that converts bits to a string, but I cant just figure it out. The server always crashes when I use it. My function is a little bit different than this one, but that's because my current code has to include the connection information, and I think there's a better way to do it:
byte[] b = new byte[100];
int k = s.Receive(b);
string packet = null;
for (int i = 0; i < k; i++)
{
Console.Write(Convert.ToChar(b[i]));
packet = packet + Convert.ToChar(b[i]);
}
I guess the function is not the problem, but how I use it is. Any help would be very much apreciated.
Edit:
I am calling and using it like this:
byte[] b = new byte[100];
string response = BitConvert(b);
if (response == "Hi there")
#2 I want the client to álways send a packet just once, with a password. And if that password doesn't match the password mentioned as a string in the server, it should close the connection with the client.
I know how to send the packet just once, but I don't know how to check the packet in the server just once for each client.
Or in other words, at the moment the server has no way of knowing if the client has already been authenticated. So I guess the client needs to have some sort of socket ID, and the server needs a table with the ID, and a boolean to see if it's autenticated or not.
The first part, getting the bytes into a string ... how about:
byte b[] = new byte[100];
int k = s.Receive(b, b.Length, 0);
string packet = Encoding.ASCII.getString(b, 0, k);
Part 2 ... not sure off the top of my head.
I'm with Rob above on part 1 and as for part 2...
Assuming you're using a TCP connection the System.Net.Sockets class should handle your
needs.
If you use either AcceptSocket or AcceptTcpClient to pull a connection from the incoming connection request queue you'll get a socket or tcpclient that is unique to that connection. simply leave it open until you're done with it. (There are also non-blocking alternatives if your service has other things to do...)
If the client closes it or opens up a new connection the will have to reauthenticate somehow. (This may be by including a token that you generate for them when they first authenticate - that's your only option if you're using UDP connections).

What does Socket.ReceiveMessageFrom()'s endpoint parameter?

I am writing a proxy application for iSCSI to do some diagnostic work (think Fiddler for iSCSI) - I'm trying to capture data one packet at a time, I don't want to read arbitrary sizes and end up getting all of one iSCSI packet and half of another - I really want to see the same kind of data as Wireshark would display for example. In doing this, I'm using Socket.ReceiveMessageFrom().
However, one of the parameters is called "endpoint", and I'm not quite sure what to do with it. Any clues? Here's my code, can you tell me if I'm completely off base:
Tuple<byte[], int> readOnePacket(TcpClient conn) {
var flags = SocketFlags.None;
EndPoint endpoint = null; /*** You can't set this to null!! ***/
byte[] buffer = new byte[10 * 0x100000];
int offset = 0;
int bytes_received;
do {
IPPacketInformation packet_information;
bytes_received = conn.Client.ReceiveMessageFrom(buffer, offset, BufferSize,
ref flags, ref endpoint, out packet_information);
if (flags == SocketFlags.Partial) {
// We only want to transfer full packets
offset = bytes_received;
continue;
}
} while (false);
return new Tuple<byte[], int>(buffer, bytes_received + offset );
}
It is not TcpClient.ReceiveMessageFrom(), but Socket.ReceiveMessageFrom()
If you take a look at the documentation, you will read the following:
An EndPoint, passed by reference, that
represents the remote server.
Edit:
Setting it to null is, indeed, a bad idea.
While not a direct answer to your question, I think this answer can still be useful (though lots of time passed since the question was asked).
Because I don't know if iSCSI works over TCP or over plain IP, I cannot offer a solution for your problem. But in general, TCP is a stream-oriented protocol, and doesn't have a notion of "message". On the other hand, IP is a datagram (i.e. message) oriented protocol, and it has notion of message. In your code, you're trying to read a "message" (IP construct) from TCP socket, and that will not work. Yes, TCP is based on IP, but IP datagrams are not visible on TCP level.
The problem you've mentioned (read full message, without reading into the next one) is applicable to TCP level only, because on IP you really can read one whole message. When you want the same thing on TCP level, you need to use a protocol with message support. Usually to achieve this you need to have you own protocol, based on TCP, with messages like this:
[msg header][msg body]
where [msg header] consists of something like:
[msg type][msg body length]
Msg type and msg body length have fixed length (say, 2 bytes for msg type and 4 bytes for body length), and msg body can have variable length, so you can read full header, then determine how long the body is, and based on that read full body.
Hope this helps.

How to can I set the Type of Service bits in C#?

I'm writing an application to send data over a network, and need to know if it is possible to set the Type of Service (ToS) bits in the IP Packet header. Anyone know if this is supported by C#, and if so how I should go about implementing it?
I know I can use a raw socket type and specify my own header, but I'd rather not have to do this as I'm only using TCP, so it seems a bit pointless to create an entire header just so I can set three bits, when it can be automatically created without these bits set.
Any suggestions would be greatly appreciated.
Wouldn't this work? (almost straight from TcpClient.Client help)
TcpClient client = new TcpClient();
Socket s = client.Client;
if (!s.Connected)
{
s.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.TypeOfService, 2);
}
Not sure what value you want to set it to, but this should work...

Categories

Resources