信息安全系统设计基础第五次实验报告

北京电子科技学院(BESTI)

实 验 报 告

课程:信息安全系统设计基础 班级: 1353

姓名:(按贡献大小排名)朱锂 陈都

学号:(按贡献大小排名)20135319 20135328

成绩: 指导教师: 娄嘉鹏 实验日期:11.10

实验密级: 预习程度: 实验时间:15:30—18:00

仪器组次: 必修/选修:必修 实验序号:5

实验名称:信息安全系统设计基础EXP5—简单嵌入式WEB服务器实验

实验目的与要求:

1 看懂代码,在宿主机和实验箱中实现。

2 查找C语言密码算法库,在通信中使用密码算法

实验内容与步骤:

1 进入/arm2410cl/exp/basic/07_httpd 目录,使用 vi 编辑器或其他编辑器阅读理解源代码

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <unistd.h>
#include <ctype.h>
#include "pthread.h"

#define DEBUG

int KEY_QUIT=0;
int TIMEOUT=30;

#ifndef O_BINARY
#define O_BINARY 0
#endif

char referrer[128];
int content_length;

#define SERVER_PORT 80

int PrintHeader(FILE *f, int content_type)
//发送http协议数据头
//参数一表示客户连接的文件流指针
//参数二表示信息类型
{
  alarm(TIMEOUT);
  fprintf(f,"HTTP/1.0 200 OK\n");
  switch (content_type)
  { 
   case 't':
    fprintf(f,"Content-type: text/plain\n");
    break;
   case 'g':
    fprintf(f,"Content-type: image/gif\n");
    break;
   case 'j':
    fprintf(f,"Content-type: image/jpeg\n");
    break;
   case 'h':
    fprintf(f,"Content-type: text/html\n");
    break;
  }
  fprintf(f,"Server: uClinux-httpd 0.2.2\n");
  fprintf(f,"Expires: 0\n");
  fprintf(f,"\n");
  alarm(0);
  return(0);
}

int DoJpeg(FILE *f, char *name)
//发送jpeg
//参数一文件数据信息
//参数二文件名
{
  char *buf;
  FILE * infile;
  int count;
 
  if (!(infile = fopen(name, "r"))) {
    alarm(TIMEOUT);
    fprintf(stderr, "Unable to open JPEG file %s, %d\n", name, errno);
    fflush(f);
    alarm(0);
    return -1;
  }
 
  PrintHeader(f,'j');   

 
  copy(infile,f); /* prints the page */
 
  alarm(TIMEOUT);
  fclose(infile);
  alarm(0);
 
  return 0;
}

int DoGif(FILE *f, char *name)
//发送gif文件
//参数一文件数据信息
//参数二文件名
{
  char *buf;
  FILE * infile;
  int count;

  if (!(infile = fopen(name, "r"))) {
    alarm(TIMEOUT);
    fprintf(stderr, "Unable to open GIF file %s, %d\n", name, errno);
    fflush(f);
    alarm(0);
    return -1;
  }

  PrintHeader(f,'g');

  copy(infile,f); /* prints the page */  

  alarm(TIMEOUT);
  fclose(infile);
  alarm(0);
  
  return 0;
}

int DoDir(FILE *f, char *name)
//发送当前目录列表信息
//参数一文件流指针用于写入目录文件信息数据
//参数二客户请求的目录信息
{
  char *buf;
  DIR * dir;
  struct dirent * dirent;

  if ((dir = opendir(name))== 0) {
    fprintf(stderr, "Unable to open directory %s, %d\n", name, errno);
    fflush(f);
    return -1;
  }
  
  PrintHeader(f,'h');
  
  alarm(TIMEOUT);
  fprintf(f, "<H1>Index of %s</H1>\n\n",name);
  alarm(0);

  if (name[strlen(name)-1] != '/') {
    strcat(name, "/");
  }
  
  while(dirent = readdir(dir)) {
    alarm(TIMEOUT);
  
    fprintf(f, "<p><a href=\"/%s%s\">%s</a></p>\n", name, dirent->d_name, dirent->d_name);
    alarm(0);
  }
  
  closedir(dir);
  return 0;
}

int DoHTML(FILE *f, char *name)
//发送 HTML 文件内容
//参数一写入文件数据信息
//参数二客户请求的文件名
{
  char *buf;
  FILE *infile;
  int count;
  char * dir = 0;

  if (!(infile = fopen(name,"r"))) {
    alarm(TIMEOUT);
    fprintf(stderr, "Unable to open HTML file %s, %d\n", name, errno);
    fflush(f);
    alarm(0);
    return -1;
  }

  PrintHeader(f,'h');
  copy(infile,f); /* prints the page */  

  alarm(TIMEOUT);
  fclose(infile);
  alarm(0);

  return 0;
}

int DoText(FILE *f, char *name)
//发送纯文本文件内容
//参数一写入文件信息数据
//参数二写入文件名
{
  char *buf;
  FILE *infile;
  int count;

  if (!(infile = fopen(name,"r"))) {
    alarm(TIMEOUT);
    fprintf(stderr, "Unable to open text file %s, %d\n", name, errno);
    fflush(f);
    alarm(0);
    return -1;
  }

  PrintHeader(f,'t');
  copy(infile,f); /* prints the page */  

  alarm(TIMEOUT);
  fclose(infile);
  alarm(0);

  return 0;
}

int ParseReq(FILE *f, char *r)
//解析客户请求,参数一表示客户连接的文件流指针
//参数二,待解析的字符串
{
    char *bp;
    struct stat stbuf;
    char * arg;
    char * c;
    int e;
    int raw;

#ifdef DEBUG
    printf("req is '%s'\n", r);
#endif
  
    while(*(++r) != ' ');  /*skip non-white space*/
    while(isspace(*r))
        r++;
  
    while (*r == '/')
        r++;
    bp = r;
  
    while(*r && (*(r) != ' ') && (*(r) != '?'))
        r++;
    
#ifdef DEBUG
    printf("bp='%s' %x, r='%s' \n", bp, *bp,r);
#endif
    
    if (*r == '?')
    {
        char * e;
        *r = 0;
        arg = r+1;
        if (e = strchr(arg,' ')) 
        {
            *e = '\0';
        }
    } else 
    {
        arg = 0;
        *r = 0;
    }
  
    c = bp;

  
    if (c[0] == 0x20){
        c[0]='.';
        c[1]='\0'; 
    }
    if(c[0] == '\0') strcat(c,".");
        
    if (c && !stat(c, &stbuf)) 
    {
        if (S_ISDIR(stbuf.st_mode)) 
        { 
            char * end = c + strlen(c);
            strcat(c, "/index.html");
            if (!stat(c, &stbuf)) 
            {
                DoHTML(f, c);
            } 
            else 
            {
                *end = '\0';
                DoDir(f,c);
            }
        }
        else if (!strcmp(r - 4, ".gif"))
            DoGif(f,c);
        else if (!strcmp(r - 4, ".jpg") || !strcmp(r - 5, ".jpeg"))
            DoJpeg(f,c);
        else if (!strcmp(r - 4, ".htm") || !strcmp(r - 5, ".html"))
            DoHTML(f,c);
             else
                  DoText(f,c);
    } 
    else{
        PrintHeader(f,'h');
        alarm(TIMEOUT);
        fprintf(f, "<html><head><title>404 File Not Found</title></head>\n");
        fprintf(f, "<body>The requested URL was not found on this server</body></html>\n");
        alarm(0);
    }
    return 0;
}

void sigalrm(int signo)
{
    exit(0);
}

int HandleConnect(int fd)//控制连接
{
  FILE *f;

  char buf[160];
  char buf1[160];

  f = fdopen(fd,"a+");
  if (!f) {
    fprintf(stderr, "httpd: Unable to open httpd input fd, error %d\n", errno);
    alarm(TIMEOUT);
    close(fd);
    alarm(0);
    return 0;
  }
  setbuf(f, 0);

  alarm(TIMEOUT);

  if (!fgets(buf, 150, f)) {
    fprintf(stderr, "httpd: Error reading connection, error %d\n", errno);
    fclose(f);
    alarm(0);
    return 0;
  }
#ifdef DEBUG
    printf("buf = '%s'\n", buf);
#endif
    
    alarm(0);

    referrer[0] = '\0';
    content_length = -1;
    
    alarm(TIMEOUT);

    while (fgets(buf1, 150, f) && (strlen(buf1) > 2)) {
        alarm(TIMEOUT);
        #ifdef DEBUG
            printf("Got buf1 '%s'\n", buf1);
        #endif
        if (!strncasecmp(buf1, "Referer:", 8)) {
            char * c = buf1+8;
            while (isspace(*c))
                c++;
            strcpy(referrer, c);
        } 
        else if (!strncasecmp(buf1, "Referrer:", 9)) {
            char * c = buf1+9;
             while (isspace(*c))
                c++;
            strcpy(referrer, c);
        } 
        else if (!strncasecmp(buf1, "Content-length:", 15)) {
            content_length = atoi(buf1+15);
        } 
    }
    alarm(0);
  
    if (ferror(f)) {
        fprintf(stderr, "http: Error continuing reading connection, error %d\n", errno);
        fclose(f);
        return 0;
    }   
    
    ParseReq(f, buf);

    alarm(TIMEOUT);
    fflush(f);
    fclose(f);
    alarm(0);
    return 1;
}



void* key(void* data)
{
    int c;
    for(;;){
        c=getchar();    
        if(c == 'q' || c == 'Q'){
            KEY_QUIT=1;
            exit(10);
            break;
        }
    }
        
}

int main(int argc, char *argv[])
{
  int fd, s;
  int len;
  volatile int true = 1;
  struct sockaddr_in ec;
  struct sockaddr_in server_sockaddr;
      
  pthread_t th_key;
  void * retval;


  signal(SIGCHLD, SIG_IGN);
  signal(SIGPIPE, SIG_IGN);
  signal(SIGALRM, sigalrm);

  chroot(HTTPD_DOCUMENT_ROOT);
  printf("starting httpd...\n");
  printf("press q to quit.\n");
// chdir("/");

  if (argc > 1 && !strcmp(argv[1], "-i")) {
    /* I'm running from inetd, handle the request on stdin */
    fclose(stderr);
    HandleConnect(0);
    exit(0);
  }

  if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
    perror("Unable to obtain network");
    exit(1);
  }
  
  if((setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&true, 
         sizeof(true))) == -1) {
    perror("setsockopt failed");
    exit(1);
  }

  server_sockaddr.sin_family = AF_INET;
  server_sockaddr.sin_port = htons(SERVER_PORT);
  server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  
  if(bind(s, (struct sockaddr *)&server_sockaddr, 
      sizeof(server_sockaddr)) == -1)  {
    perror("Unable to bind socket");
    exit(1);
  }

  if(listen(s, 8*3) == -1) { /* Arbitrary, 8 files/page, 3 clients */
    perror("Unable to listen");
    exit(4);
  }

  
    pthread_create(&th_key, NULL, key, 0);
  /* Wait until producer and consumer finish. */
  printf("wait for connection.\n"); 
  while (1) {
      
    len = sizeof(ec);
    if((fd = accept(s, (void *)&ec, &len)) == -1) {
      exit(5);
      close(s);
    }
    HandleConnect(fd);
    
  }
  pthread_join(th_key, &retval);
}

2 编译应用程序 运行 make 产生可执行文件 httpd

[root@zxt /]# cd /arm2410cl/exp/basic/07_httpd/
[root@zxt 07_httpd]# make
armv4l-unknown-linux-gcc -DHTTPD_DOCUMENT_ROOT=\"/mnt/yaffs\" -c -o httpd.o httpd.c
armv4l-unknown-linux-gcc -DHTTPD_DOCUMENT_ROOT=\"/mnt/yaffs\" -c -o copy.c
armv4l-unknown-linux-gcc -o ../bin/httpd httpd.o copy.o -lpthread
armv4l-unknown-linux-gcc -o httpd httpd.o copy.o -lpthread
[root@zxt 07_httpd]# ls
copy.c doc httpd httpd.o Makefile
copy.o Google httpd.c index.html Makefile.bak

3 下载调试 使用 NFS 服务方式将 HTTPD 下载到开发板上,并拷贝测试用的网

页进行调试,本例中用的是 index 测试网页。

[/mnt/yaffs] mount -t nfs -o nolock 192.168.0.56:/arm2410cl /host
[/mnt/yaffs]cd /host/exp/basic/07_httpd/
[/host/exp/basic/07_httpd]./httpd
starting httpd...
press q to quit.
wait for connection.

实验体会:

通过这次实验,我们又知道了一种嵌入式系统的应用方法,由于操作的层面比通常开发web应用所在层次更加底层,这对于我们对于web应用的深入理解也是一种加强。

你可能感兴趣的:(信息安全系统设计基础第五次实验报告)