首页 网络安全 安全学院 查看内容

C实现简单web服务器

2009-8-28 11:10 933 0

摘要: //simple HTTP server for Windows NT //created by int3 //supports GET, HEAD, other method not support...
关键词: nbsp HTTP outdata server body filename SIZE char return addr

//simple HTTP server for Windows NT //created by int3 //supports GET, HEAD, other method not support //allows access to files in certain directory //echos version back, but disconnects connection always so act like HTTP/1.0 //current version not support directory, only file, future version fix problem  #include <winsock2.h> #include <windows.h> #include <stdio.h>  #define HTTP_SERVER_PORT 80 #define HTTP_SERVER_OUTPUT_HEAD "HTTP/%d.%d 200 OK\n" "Date: %s" "Server: Windows\n" "Last-Modified: Tue, 15 Nov 2005 13:24:10 GM T\n"\  "Accept-Ranges: bytes\n" "Content-Length: %d\n" "Connection: close\n" "Content-Type: text/html; charset=ASCII\n\n" #define METHOD_NOT_IMPLEMENTED "<html><head><title>BAD REQUEST</title></head><body><h1>BAD REQUEST: HTTP STATUS CODE 501</h1></body></html>" #define HTTP_ERROR_404 "<html><head><title>ERROR CODE 404</title></head><body><h1>PAGE NOT FOUND: HTTP STATUS CODE 404</h1></body></html>" #define HTTP_RECV_SIZE 1024 #define HTTP_HEADER_SIZE 1024 int http_server; int ctrl_c_handler(DWORD x); int accept_loop(int g); char http_dir[256]; struct sockaddr_in my_addr; char *http_read_file(char *filename, char **body);  int main(int argc, char **argv) {  WSADATA wsadata;  SetConsoleCtrlHandler((PROC) ctrl_c_handler, TRUE);  if (argc != 2) {   puts("server files_dir");   return 1;  }  strncpy(http_dir, argv[1], 256);  http_dir[255] = 0; //insert null terminator  if (WSAStartup(0x202, &wsadata) != 0) {   puts("WSAStartup failed");   return 1;  }  http_server = socket(AF_INET, SOCK_STREAM, 0); //create socket  if (http_server == -1) {   puts("socket failed");   return 1;  }  my_addr.sin_family = AF_INET;  my_addr.sin_port = htons(HTTP_SERVER_PORT);  my_addr.sin_addr.s_addr = INADDR_ANY;  if (bind(http_server, &my_addr, sizeof(my_addr)) == -1) { //bind to port   puts("socket failed");   return 1;  }  if (listen(http_server, 1) == -1) { //listen on port   puts("listen failed");   return 1;  }  accept_loop(0);  return 0; }  int ctrl_c_handler(DWORD x) {  puts("terminate server");  fflush(stdout);  closesocket(http_server);  WSACleanup(); //close winsock  ExitProcess(0); }  int accept_loop(int g) {  struct sockaddr_in r_addr;  while (1) {   char filename[256];   char indata[HTTP_RECV_SIZE+1];   char *outdata;   int sin_size = sizeof(r_addr);   int http_client = accept(http_server, &r_addr, &sin_size);   int data_read;   int ver1, ver2;   time_t t = time(0); //get time   char *ch;   char *body = 0;   int body_size;   CreateThread(NULL, 0, (PROC) accept_loop, 0, 0, NULL); //create new thread   if (http_client == -1) {    puts("accept failed");    return 1;   }   printf("New connection by %s\n", inet_ntoa(r_addr.sin_addr)); //display remote IP address   fflush(stdout); //send to output   data_read = recv(http_client, indata, HTTP_RECV_SIZE, 0);   if (data_read == -1) {    puts("recv failed");    return 1;   }   indata[data_read] = 0; //null terminator   ch = strstr(indata, "HTTP/");   sscanf(ch, "HTTP/%d.%d", &ver1, &ver2);   if (!strncmp(indata, "GET", 3)) {    sscanf(indata, "GET %255s", filename);    body = http_read_file(filename, &body);    if (body != NULL) {     body_size = strlen(body);     outdata = malloc(body_size + HTTP_HEADER_SIZE);     sprintf(outdata, HTTP_SERVER_OUTPUT_HEAD "%s", ver1, ver2, ctime(&t), body_size, body); //write head+body to buffer    }    else {     outdata = malloc(strlen(HTTP_ERROR_404) + 1);     strcpy(outdata, HTTP_ERROR_404);    }   } else if (!strncmp(indata, "HEAD", 4)) {    sscanf(indata, "HEAD %255s", filename);    body = http_read_file(filename, &body);    if (body != NULL) {     body_size = strlen(body);     outdata = malloc(HTTP_HEADER_SIZE);     sprintf(outdata, HTTP_SERVER_OUTPUT_HEAD, ver1, ver2, ctime(&t), body_size); //write head to buffer    }    else {     outdata = malloc(strlen(HTTP_ERROR_404) + 1);     strcpy(outdata, HTTP_ERROR_404);    }   } else if (!strncmp(indata, "OPTIONS", 7)) { //NOT IMPLEMENTED YET    outdata = malloc(strlen(METHOD_NOT_IMPLEMENTED) + 1);    strcpy(outdata, METHOD_NOT_IMPLEMENTED);   } else { //SO FAR POST, etc. NOT IMPLEMENTED    outdata = malloc(strlen(METHOD_NOT_IMPLEMENTED) + 1);    strcpy(outdata, METHOD_NOT_IMPLEMENTED);   }   //puts(indata); //display request   send(http_client, outdata, strlen(outdata), 0); //send data   free(outdata);   free(body); //free memory invalid:   closesocket(http_client);  } }  //read file filename from html dir into buffer body char *http_read_file(char *filename) {  FILE *f;  char fname[512];  int size;  char *ch = filename;  char *buffer;  int access_denied = 0;  strcpy(fname, http_dir);  while (*ch != 0) {   if (*ch == '/')    *ch = '\\';   if (*ch == '.')    if (*(ch+1) == '/')     access_denied = 1; //deny access ./ to rm ../ vuln   ch++; //next char  }  strcat(fname, filename);  if (access_denied == 1) {   printf("access denied: filename %s\n", fname);   return NULL;  }  f = fopen(fname, "rb"); //open file for read  if (f == NULL) {   printf("file open failed: filename %s\n", fname);   return NULL;  }  fseek(f, 0, 2); //seek to end  size = ftell(f);  rewind(f);  if ((buffer = malloc(size + 1)) == NULL) {   puts("error: memory allocation failed");   exit(1);  }  if (fread(buffer, size, 1, f) == -1) {//read file   printf("file read failed: filename %s\n", fname);   free(buffer);   return NULL;  }  buffer[size] = 0; //null terminator  return buffer;  
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部