Created
December 14, 2012 17:08
-
-
Save danpalmer/4287012 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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