determining HTTP version using raw sockets in C - c++

I am trying to create raw sockets in C/C++, then create a request message and then send that message to a target server. If the port I specify happens to be 80 I want to send a HTTP request to determine the HTTP version that the target server is using. For e.g I send GET HTTP/1.0 to www.google.com.
For some servers it returns HTTP/1.1 400 bad request. While in some cases it responds with an XML message. I know the GET command is wrong since I am not specifying any object to actually GET. So is there a generic way to do this?

Try:
HEAD / HTTP/1.0\r\n
\r\n
Or:
GET / HTTP/1.0\r\n
\r\n
The first line of the servers response should contain the HTTP version. Note that some servers will return 400 Bad Request if the Host: <hostname> is omitted from the header (which is not required in 1.0, but in 1.1). I would do:
Try:
HEAD / HTTP/1.0\r\n
Host: <hostname>\r\n
\r\n
Or:
GET / HTTP/1.0\r\n
Host: <hostname>\r\n
\r\n
If you don't require the message body, you should use HEAD as it will require less data to receive.

You will have to progressively try each version of HTTP. For example, if I query google.com with HTTP 1.0, it will respond with HTTP 1.0:
$ printf "HEAD / HTTP/1.0\nHost: google.com\n\n" | nc google.com 80
HTTP/1.0 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Tue, 26 Nov 2013 19:44:42 GMT
Expires: Thu, 26 Dec 2013 19:44:42 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Alternate-Protocol: 80:quic
If I query it with HTTP 1.1, it will respond with HTTP 1.1:
$ printf "HEAD / HTTP/1.1\nHost: google.com\n\n" | nc google.com 80
HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Tue, 26 Nov 2013 19:44:47 GMT
Expires: Thu, 26 Dec 2013 19:44:47 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Alternate-Protocol: 80:quic

GET / HTTP/1.0\r\n
Host: www.google.com\r\n
\r\n
This is a basic HTTP request. Alternatively, you can use HEAD instead of GET, sinse you only want the headers, but some basic servers don't recognize HEAD as a valid method.
Not every server will support HTTP/1.0, they will most likely ignore this and answer as HTTP/1.1, others will just ape the version in your request and not really mean it.
It can be frustrating to try to determine the HTTP version in a random server. Perhaps you should instead use 1.1 in the request and see if the server answers with 1.0, I believe it may be the safest way to know if the server is at least giving a damn.

Related

Getting java.net.URISyntaxException: Illegal character in path at index 7: http:/${Bearer}

I have an API name loginUser, which generates the authorization Token, that is to be passed in other subsequent APIs.
Below is the response:-
HTTP/1.1 200 OK
Date: Sat, 10 Nov 2018 07:08:45 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 71
Connection: keep-alive
Server: nginx/1.10.3 (Ubuntu)
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: date, authorization, x-powered-by, connection, server, access-control-allow-origin, content-type, content-length, x-final-url
authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIyYmEyYjc1My03NWEwLTQxNGYtYWFiOC0zZGY1M2I4YmIwMDEiLCJpc0Nvb2siOnRydWUsImlhdCI6MTU0MTgzMzcyNX0.3FRVpHm4EF2Ahzzy-OjbZ2EeZto6-hSFKHNtG5wcjBs
Where I want to fetch the authorization.
I'm using Regular Expression Extractor, but it is throwing below error (URISyntaxException: illegal character in the path)
Snapshots:-
Step_1
Step_4
I have seen couple of queries related to this Error but not in Jmeter,
And i tried using % also, to get rid out of this error, but that didn't work out.
Thanks in advance.
Authorization is sent/receive in headers,
Change Step 2, Field to check should be Response Headers to get the value

OAuth2 with beast boost returns temporary redirect 307

I'm trying to implement an app with access to google drive in beast boost C++ usingoauth2 authentication.
https://developers.google.com/identity/protocols/OAuth2ForDevices
I try to get the user code in Postman with the following POST request:
POST /o/oauth2/device/code HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file&client_id=610490019085-l1v2mv7lv95lu7cr111vbtqmp1bigv42.apps.googleusercontent.com
And it works perfectly fine, returning:
{
"verification_url": "https://www.google.com/device",
"expires_in": 1800,
"interval": 5,
"device_code": "AH-1Ng0IgBnIXIUeltwDoL7AwNExNTT0rozdxD5FMnP8dip4DaDi8_XtzK2aVT92YKYmYa7KWqHRVqw5AmJCDtalzK3k6pvbFw",
"user_code": "LWZY-BDXD"
}
Now I want to do the same request in C++ using boost, with the following code snippet for the request:
http::request<http::string_body> req{http::verb::post, "/o/oauth2/device/code", 11};
req.set(http::field::host, "accounts.google.com");
req.set("Cache-Control", "no-cache");
req.set(http::field::content_type, "application/x-www-form-urlencoded");
req.body() = "scope=https://www.googleapis.com/auth/drive.file&client_id=610490019085-l1v2mv7lv95lu7cr111vbtqmp1bigv42.apps.googleusercontent.com";
req.prepare_payload();
This one returns:
HTTP/1.0 307 Temporary Redirect
Content-Type: text/html; charset=UTF-8
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Date: Mon, 14 May 2018 11:06:01 GMT
Location: https://accounts.google.com/o/oauth2/device/code
Content-Length: 232
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
<HTML>
<HEAD>
<TITLE>Temporary Redirect</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Temporary Redirect</H1>
The document has moved here.
</BODY>
</HTML>
Any ideas how I can get the JSON returned as with Postman?
Thank You!
Beast is a low-level protocol library, it doesn't know anything about resolving domain names or connecting sockets. It doesn't even know about TCP/IP, just how to serialize and deserialize HTTP/1 messages over objects which meet Asio's stream concept requirements (examples: SyncReadStream, or AsyncWriteStream). You have to handle redirects yourself. If you get a redirect response, extract the Location field value and parse the URI, resolve the domain, and then issue another GET request for the specified resource.
It is my hope that other folks (maybe you?) will build on top of beast and provide higher-level functionality like this in the form of open source libraries.

primefaces.download response cookie not set in browser

I'm trying so setup file Download for primefaces as described here: https://www.primefaces.org/showcase/ui/file/download.xhtml
Primefaces version 6.
There is a cookie called primefaces.download that needs to be set during the download process, in order to monitor the download process using javascript.
The response header has these cookie set as you can see bellow:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Powered-By: JSF/2.0
X-UA-Compatible: IE=edge
X-UA-Compatible: IE=edge
X-UA-Compatible: IE=edge
X-UA-Compatible: IE=edge
X-UA-Compatible: IE=edge
Content-Disposition: attachment;filename="aggregatedContent"
Set-Cookie: primefaces.download=true
Content-Type: text/plain
Transfer-Encoding: chunked
Date: Tue, 11 Jul 2017 05:42:41 GMT
But when I look in Chrome in the Application->Cookies, this cookie is not there.This is true for Firefox and Internet explorer as well.
Also, typing in console document.cookie does not return this set cookie.
P.S. The request is a POST with status 200 returned from a request URL on localhost.
Any ideas?

how to capture the Cookies in HttpQueryInfo using wininet c++

Currently I'm facing an issue in capturing the Cookies which is coming as part of response. I'm using WinInet for my connection.
After sending the request using HttpSendRequest, I'm using HttpQueryInfo to query the response in the below order
HTTP_QUERY_STATUS_CODE
HTTP_QUERY_SET_COOKIE
HTTP_QUERY_CONTENT_TYPE
HTTP_QUERY_CONTENT_LENGTH
Finally I'm reading body content using InternetReadFile.
Server has the loadbalance installed. all the response sent from LB has "Set-Cookies" enabled.
If I get any response without "Set-Cookies" in header then my code is reading the content successfully.
When there is "Set-Cookies" field in header then the issue comes. It is resulting out in "Header Not Found" when I query for "HTTP_QUERY_CONTENT_TYPE"
Below is the sample response header which is success
HTTP/1.1 200 OK
Cache-Control: private
Server: Microsoft-IIS/8.5
X-Powered-By: ASP.NET
Date: Thu, 17 Dec 2015 10:05:00 GMT
Content-Length: 107
Content-Type: text/html; Charset=utf-8
Via: 1.1 TestServer:80 (Cisco-WSA/8.8.0-085)
Connection: keep-alive
Below is the sample response header which is error out.
HTTP/1.1 200 OK
Cache-Control: private
Server: Microsoft-IIS/8.5
Set-Cookie: MYID=B3C5D2B2%2D0426%2D473F%2DACF6%2DF19BAC3F5A6C%3A%3A88757401; path=/
X-Powered-By: ASP.NET
Date: Thu, 17 Dec 2015 10:07:20 GMT
Content-Length: 277
Content-Type: text/html; Charset=utf-8
Via: 1.1 TestServer:80 (Cisco-WSA/8.8.0-085)
Connection: keep-alive
Work around found,
While querying the response header, if I add HTTP_QUERY_COOKIE in the sequence then the issue is getting resolved but I'm not sure on this is correct or not.
Can any one help me?
Why SET_COOKIE is not able to catch the "set-cookies"
What is the difference between HTTP_QUERY_SET_COOKIE and HTTP_QUERY_COOKIE?
What will be the impact if I use HTTP_QUERY_COOKIE to overcome this issue?
Thanks
Vijay

How to connect a socket to an http server through proxy?

Recently I wrote a program using sockets in C, to connect to an HTTP server running locally and thereby to do requests to that.
That worked fine for me. After that I tried the same code to connect to another server on the web (e.g. www.google.com), but I was not able to connect and was getting another html response from the proxy server in my network.
My local IP is: 10.0.2.58
The proxy IP is: 10.0.0.1
This is the response I got :
HTTP/1.1 302 Found
Expires: Fri, 10 Feb 2012 12:47:35 GMT
Expires: 0
Cache-Control: max-age=180000
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
Connection: close
Location: http://10.0.0.1:8000/index.php?redirurl=http%3A%2F%2F10.0.2.58%2F
Content-type: text/html
Content-Length: 0
Date: Wed, 08 Feb 2012 10:47:35 GMT
Server: lighttpd/1.4.29
How can I bypass this proxy to connect to external servers?
Response got when tried with CONNECT
HTTP/1.1 302 Found
Expires: Fri, 10 Feb 2012 13:37:58 GMT
Expires: 0
Cache-Control: max-age=180000
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
Connection: close
Location: http://10.0.0.1:8000/index.php?redirurl=http%3A%2F%2F10.0.2.58http%3A%2F%2Fwww.google.com%2F
Content-type: text/html
Content-Length: 0
Date: Wed, 08 Feb 2012 11:37:58 GMT
Server: lighttpd/1.4.29
Working code which connect's to my local apache
#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<string.h>
#define MAX_BUFFER_SIZE 1024
int main(int argc,char *argv[])
{
int clsd,ssd,status;
char buffer[1024];
char request[]="GET / HTTP/1.1\r\nHost:10.0.2.58\r\n\r\n";
struct sockaddr_in srvr_addr;
struct addrinfo hints,*res;
srvr_addr.sin_family=AF_INET;
srvr_addr.sin_port=htons(80);
srvr_addr.sin_addr.s_addr=inet_addr("10.0.2.58");//Local server
clsd =socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(clsd<=0)
{
perror("Socket init failed..\n");return 1;
}
ssd=connect(clsd,(struct sockaddr *)&srvr_addr,(socklen_t)(sizeof srvr_addr));
if(clsd<=0)
{
perror("Socket connect failed..\n");return 1;
}
write(clsd,request,strlen(request));
memset((void *)&request,0x00,strlen(request));
memset(&buffer,0x00,MAX_BUFFER_SIZE);
do
{
status=read(clsd,&buffer,MAX_BUFFER_SIZE);
write(1,&buffer,status);
memset((void *)&request,0x00,strlen(request));
memset(&buffer,0x00,MAX_BUFFER_SIZE);
do
{
status=read(clsd,&buffer,MAX_BUFFER_SIZE);
write(1,&buffer,status);
}while(status>0);
close(clsd);
return 0;
}
To use connections via proxy (or if they are implicitly proxy-fied), first you should connect to proxy, send a 'CONNECT' message with target host; proxy will establish connection and return you data.
Here is in steps:
open socket to proxy host
send 'CONNECT http://www.google.com:80 HTTP/1.0\r\n\r\n' string
wait for recv
You must specify protocol (in our case is HTTP 1.0, non-chunked) with ending newline characters, so proxy knows how to communicate with end point.
You can find details about CONNECT method at http://www.ietf.org/rfc/rfc2817.txt
If you're specifically trying to bypass the proxy, you should talk to whoever administers your network to find out if that's even possible. If your first block of output is an attempt to connect to Google then it appears to me that there's some kind of transparent proxy on your network that you'll have to take special (and network-specific) steps to bypass.
Of course, if you're just interested in getting data, you could try following the redirect...