0

I am currently trying to send a full POST request with C to my local server where my PHP page will consume the request and INSERT the request into the database.

If I use the form I created to insert into the database, it works perfect.

But I'm trying to do the same POST request but in C to INSERT INTO the database. I'm not sure how to make the POST request. I intercepted the request with Burp so I know the request will be perfect and work. I'm just not sure how to implement it in my C program.

I have included my current C code to send the HTTP POST request.

I get a good reply, but nothing inserts into the database

/*
Create a TCP socket
*/

#include<stdio.h>
#include<winsock2.h>

#pragma comment(lib,"ws2_32.lib") //Winsock Library


int main(int argc , char *argv[])
{
    WSADATA wsa;
    SOCKET s;
    struct sockaddr_in server;
    char *message , server_reply[2000];
    int recv_size;

    printf("\nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
    {
        printf("Failed. Error Code : %d",WSAGetLastError());
        return 1;
    }

    printf("Initialised.\n");

    //Create a socket
    if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
    {
        printf("Could not create socket : %d" , WSAGetLastError());
    }

    printf("Socket created.\n");


    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_family = AF_INET;
    server.sin_port = htons(80);

    //Connect to remote server
    if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
    {
        puts("connect error");
        return 1;
    }

    puts("Connected");


    char* str2;
    char* str3;
    char* str5;
    char* str20;

    str2 = "POST /project2/public/addJoke.php HTTP/1.0\r\n";
    str3 = "Content-Type: text/plain\r\n";
    str20= "Content-Length: 12\r\n\r\n";
    str5 = "joketext=ctest&jokedate=2018-01-01";

    char * message2 = (char *) malloc(1 + strlen(str2)+ strlen(str3)+ strlen(str5) + strlen(str20));

    strcpy(message2,str2);
    strcat(message2,str3);
    strcat(message2,str20);
    strcat(message2,str5);




    if( send(s , message2 , strlen(message2) , 0) < 0)

    {
        puts("Send failed");
        return 1;

    }
    puts("Data Send\n");

    //Receive a reply from the server
    if((recv_size = recv(s , server_reply , 2000 , 0)) == SOCKET_ERROR)
    {
        puts("recv failed");
    }

    puts("Reply received\n");

    //Add a NULL terminating character to make it a proper string before printing
    server_reply[recv_size] = '\0';
    puts(server_reply);

    return 0;
}

And here is my PHP file that receives the request.

if(isset($_POST['joketext'])){

try{

include __DIR__ . '/../includes/databaseconnection.php';

$title = 'Good Connection';

$sql = 'INSERT INTO jokes.jokes_tbl SET
joketext = :joketext,
jokedate = CURDATE(),
authorid = :authorid';

$stmt = $pdo->prepare($sql);
$stmt->bindValue(':joketext', $_POST['joketext']);
$stmt->bindValue(':authorid', $_POST['authorid']);
$stmt->execute();

header('location: jokeslist.php');

}catch(PDOException $err){
$title = 'Bad Connection';
$output = 'Bad Connection' . 
$err->getMessage() . ' in ' . 
$err->getFile() . ':' . $err->getLine(); 
}
}else{
 ob_start();
include __DIR__ . '/../templates/addJoke.html.php';
$output = ob_get_clean();
}
include __DIR__ . '/../templates/layout.html.php';
  • Oh, what happened to the markup? – alk May 21 '18 at 12:47
  • 1
    If you're asking how to send a POST requesting using C and Berkeley sockets, did you try [searching on this very site](https://stackoverflow.com/questions/22077802/simple-c-example-of-doing-an-http-post-and-consuming-the-response) ? – WhozCraig May 21 '18 at 13:01

1 Answers1

2

I intercepted the request with Burp so I know the request will be perfect and work.

Only it's not:

    message = "POST /project2/public/addJoke.php HTTP/1.1
...
upgrade-Insecure-Requests: 1
joketext=test200&authorid=1"

With some basic understanding of HTTP one can see that there is no marker which ends the HTTP header and starts the HTTP body, i.e. an empty line between header and body is missing. This means that joketext=test200&authorid=1 is treated by the server as part of the header (albeit with invalid syntax) and that since no end-of-header marker is used the header is considered incomplete and thus also no body is detected. Second problem is that the line end you use is probably \n and not \r\n as it should be.

Also, you are assuming that send will send everything in the buffer and only check for errors:

   if( send(s , message , strlen(message) , 0) < 0)

Only, send does not have such a guarantee. Instead you need to check the return value for the number of bytes actually send and do another send with any remaining (unsent) data. For small buffers like this you'll probably only need a single send but for larger buffers you will run into problems.

In general: HTTP is way more complex than you might think from barely looking at some HTTP requests. There is standard for a reason and anybody coding HTTP directly should study and understand the standard. Looking at a few requests as example is not sufficient, especially if one fails to look closely enough and is thus missing details of the white space line new lines, i.e. where it belongs and what the white space is made of.

EDIT: it looks like the OP has heavily edited the code in the question which now results in new problems:

str2 = "POST /project2/public/addJoke.php HTTP/1.0\r\n";
str3 = "Content-Type: text/plain\r\n";
str20= "Content-Length: 12\r\n\r\n";
str5 = "joketext=ctest&jokedate=2018-01-01";

Obviously the length of 12 given in str20 does not match the length of the actual body in str5 which is 34. And, the formular expects a Content-Type of application/x-www-form-urlencoded instead of text/plain. Both things were correct in the original question but are now wrong. Therefore I will again repeat my above recommendation: "... anybody coding HTTP directly should study and understand the standard. Looking at a few requests as example is not sufficient..."

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Hi Steffen, Im managing to now get a successful reply from the server using a POST request, just cannot insert into database. – Jack Wilson May 22 '18 at 08:28
  • 1
    @JackWilson: Your original question was fully answered but you've made changes to your code after the answer and introduced new problems. Please stop such editing which essentially makes your question a moving target which changes its meaning and instead ask a new question. – Steffen Ullrich May 22 '18 at 08:46