/*
 * Sample server for remote exploitation
 *
 * Gaining a remote shell by exploiting this should be good
 * enough
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <assert.h>
#include <signal.h>

/* 
 * with a forking daemon cooked with unlimited spice and a small container,
 * you should be able to exploit this bug very reliably
 */

void process_client(int sock)
{
   char buf1[512];
   char buf2[1024];
   int ret;

   while(1) {
      ret = recv(sock, buf2, sizeof(buf2) - 1, 0);

      if(ret <= 0) {
         shutdown(sock, SHUT_RDWR);
         close(sock);
         return;
      }

      ret = sprintf(buf1, buf2);
      send(sock, buf1, ret, 0);
   }
}

void start_server()
{
   static int bsock;
   static int asock;
   struct sockaddr_in baddr;
   struct sockaddr_in caddr;
   int ret;
   int socklen;

   bsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   assert(bsock != -1);

   baddr.sin_addr.s_addr = INADDR_ANY;
   baddr.sin_port = htons(31337);
   baddr.sin_family = AF_INET;

   ret = bind(bsock, (struct sockaddr*) &baddr, sizeof(baddr));
   assert(ret == 0);

   ret = listen(bsock, 100);
   assert(ret == 0);
   
   signal(SIGCHLD, SIG_IGN);
   while(1) {
      socklen = sizeof(caddr);
      asock = accept(bsock, (struct sockaddr*) &caddr, &socklen);

      printf("Connection received from %s:%hd\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
      ret = fork();
      assert(ret != -1);

      if(ret == 0) {
         close(bsock);
         process_client(asock);
      }
      else {
         close(asock);
      }
   }
}

int main(int argc, char **argv)
{
   start_server();
}
