Skip to content

Instantly share code, notes, and snippets.

@danpalmer
Created December 14, 2012 17:08
Show Gist options
  • Save danpalmer/4287012 to your computer and use it in GitHub Desktop.
Save danpalmer/4287012 to your computer and use it in GitHub Desktop.
//
// Compile:
// gcc -o server server.c -O0 -fno-stack-protector \
// -mpreferred-stack-boundary=2 -ggdb
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define PORT_NUMBER "8000"
#define MAX_WAITING_CONNECTIONS 10
#define MAXDATASIZE 8096
char buffer[MAXDATASIZE];
void handle(int connfd);
void strip_directory_traversal(char *input, char *valid);
int main (int argc, char const *argv[])
{
struct addrinfo hints, *res;
struct sockaddr_storage remote_addr;
int sockfd, connfd;
socklen_t sin_size;
// Set up the socket
fprintf(stdout, ">> Setting up socket...\n");
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, PORT_NUMBER, &hints, &res);
sockfd=socket(res->ai_family, res->ai_socktype, res->ai_protocol);
// Bind to port number (might fail)
fprintf(stdout, ">> Binding to port %s\n", PORT_NUMBER);
bind(sockfd, res->ai_addr, res->ai_addrlen);
// Listen for connections
fprintf(stdout, ">> Listening...\n");
listen(sockfd, MAX_WAITING_CONNECTIONS);
// Wait and accept new connections
while (1) {
sin_size = sizeof(remote_addr);
connfd = accept(sockfd,
(struct sockaddr *)&remote_addr,
&sin_size);
if (connfd == -1) {
fprintf(stderr, "!! Connection failed, continuing\n");
continue;
} else {
fprintf(stdout, "++ Connection established\n");
}
handle(connfd);
close(connfd);
}
return 0;
}
void handle(int connfd) {
int num_bytes = recv(connfd, buffer, MAXDATASIZE, 0);
fprintf(stdout, " Buffer located at %p\n", buffer);
if (strncmp(buffer, "GET ", 4) && strncmp(buffer, "get ", 4)) {
fprintf(stdout, "-- Unsupported method, closing connection\n");
send(connfd, "501 Not Implemented", 19, 0);
return;
}
fprintf(stdout, " Parsing Request\n");
int i;
for (i = 4; i < num_bytes; i++) {
if (buffer[i]==' ' || buffer[i]=='\r' || buffer [i]=='\n') {
buffer[i] = 0;
}
}
if(!strncmp(&buffer[0],"GET /",5)
|| !strncmp(&buffer[0],"get /",5)) {
(void)strcpy(buffer,"GET /index.html");
}
char safe_filename[255];
strip_directory_traversal(&buffer[5], &safe_filename);
FILE *fp = fopen(safe_filename, "r");
if (fp == NULL) {
fprintf(stdout, " 404 - Couldn't open file\n");
send(connfd, "HTTP/1.0 404 Not Found\n\n", 24, 0);
fprintf(stdout, "-- Disconnected\n");
return;
}
fprintf(stdout, " Sending file...\n");
while ((num_bytes=fread(buffer,sizeof(char),MAXDATASIZE,fp))>0) {
send(connfd, buffer, num_bytes, 0);
}
fclose(fp);
fprintf(stdout, "-- Disconnected\n");
}
void strip_directory_traversal(char *input, char *valid) {
int offset = 0;
while (input[offset] == '.' || input[offset] == '/') {
offset++;
}
strcpy(valid, &input[offset]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment