tiny6410的文件安全传输,基于linux的

#include "client.h"

//----------------------处理函数---------------------------
void mainMenu();//主菜单
void log();   //显示log
int connectto(int argc,char *args[]);             //与服务器建立连接
int login(char username[],char userpasswd[]);  //登陆
int senddata(struct FilePackage data);        //发送数据包
int recvdata(struct FilePackage *data);           //接收数据
void Show(char temp[100]);           //显示客户端以及服务器目录
void * UpdateF(void *);            //上传文件
void * DownloadF(void *);           //下载文件
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//~~~~~~~~~~~~~~~~~~~~~~全局变量~~~~~~~~~~~~~~~~~~~~~~~~~~~
char username[50];   //用户的名字
char tempuname[50];
char userpasswd[20];  //用户的密码
int  sockclient;
struct sockaddr_in sockaddr1;
char ipaddr[15];
SSL_CTX *ctx;
SSL *ssl;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ShowCerts(SSL * ssl)
{
  X509 *cert;
  char *line;

  cert = SSL_get_peer_certificate(ssl);
  if (cert != NULL) {
    printf("Digital certificate information:\n");
    line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
    printf("Certificate: %s\n", line);
    free(line);
    line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
    printf("Issuer: %s\n", line);
    free(line);
    X509_free(cert);
  }
  else
    printf("No certificate information!\n");
}

//~~~~~~~~~~~~~~~~~~~~~~~显示LOG~~~~~~~~~~~~~~~~~~~~~~~~~~~

void log()
{
 system("clear");
 printf("       \033[36m***********\033[0m\033[34mWelcome to Secure File Storage System\033[0m\033[36m***********\n\033[0m");
 printf("       \033[36m*\033[0m \033[31m        ******     ******     ******     ******   \033[0m  \033[36m    *\n\033[0m\033[0m");
 printf("       \033[36m*\033[0m \033[31m       **          *         **         **        \033[0m  \033[36m    *\n\033[0m\033[0m");
 printf("       \033[36m*\033[0m \033[31m        *****      ******     *****      *****    \033[0m  \033[36m    *\n\033[0m\033[0m");
 printf("       \033[36m*\033[0m \033[31m            **     *              **         **   \033[0m  \033[36m    *\n\033[0m\033[0m");
 printf("       \033[36m*\033[0m \033[31m       ******      *         ******     ******  \033[0m \033[34mKJC  \033[0m  \033[36m*\n\033[0m\033[0m");
 printf("       \033[36m***********************************************************\n\033[0m");
 sleep(1);
}
//~~~~~~~~~~~~~~~~~~~~~connect to server~~~~~~~~~~~~~~~~~~~
//成功返回1,失败返回0并且退出
int connectto(int argc,char *args[])     //就是第二个函数必须是ip指针
{
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~判断输入IP是否正确~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 int i,count=0;
 if(argc!=2)
  {
   printf("format error: you mast enter ipaddr like this : client 192.168.0.6\n");
   exit(0);
  }
 for(i=0;*(args[1]+i)!='\0';i++)
  {
   if(*(args[1]+i)=='.')
    count++;
  }
 if(count!=3)   //这就是ip地址的一种检查
  {
   printf("IP format error\n");
   exit(0);
  }
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 if((sockclient=socket(AF_INET,SOCK_STREAM,0))==-1)
  {
   perror("socket"); 
   exit(0);
  }
 memset(&sockaddr1,0,sizeof(sockaddr1));
 sockaddr1.sin_family = AF_INET;
 sockaddr1.sin_addr.s_addr = inet_addr(args[1]);
 sockaddr1.sin_port = htons(port);
 
 if(connect(sockclient,(struct sockaddr* )&sockaddr1,sizeof(sockaddr1))==-1)
  {
   perror("connect");
   exit(0);
  }
  //-----------------------------------------------------------------------
 /* 基于 ctx 产生一个新的 SSL */
  ssl = SSL_new(ctx);
  SSL_set_fd(ssl, sockclient);
  /* 建立 SSL 连接 */
  if (SSL_connect(ssl) == -1)
    ERR_print_errors_fp(stderr);
  else
  {
    printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
    ShowCerts(ssl);
  }
 return 1;
}
//~~~~~~~~~~~~~~~~~~~~~~~发送数据包~~~~~~~~~~~~~~~~~~~~~~~~
int senddata(struct FilePackage data)
{
 if((SSL_write(ssl,&data,sizeof(struct FilePackage)))==-1)
  { 
   perror("send login message:");
   return 0;
  }
 return 1;
}
//~~~~~~~~~~~~~~~~~~~~~~~接收数据包~~~~~~~~~~~~~~~~~~~~~~~
int recvdata(struct FilePackage *data)
{
 if((SSL_read(ssl,data,sizeof(struct FilePackage)))==-1)
 { 
  perror("recv login message:");
  return 0;
 }
 return 1;
}

//~~~~~~~~~~~~~~~~~~~~~用户登陆~~~~~~~~~~~~~~~~~~~~~~~~~~~
//传送格式username*userpasswd#
int login(char username[20],char userpasswd[10])
{

top: printf("ID: ");
 scanf("%s",username);
 strcpy(tempuname,username);
 printf("PASSWD: ");
 scanf("%s",userpasswd);
 strcat(username,"*");
 strcat(username,userpasswd);
 strcat(username,"#");
// printf("%s\n",username);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 struct FilePackage data;
 data=pack('L', username, " ",  0, 9,strlen(username),tempuname);  //用户登录之后打包
// printf("%s\n",username);
 if(senddata(data)==0)
  exit(0);
// printf("%s\n",username);
 if(recvdata(&data)==0)
  exit(0);
// printf("%s\n",username);
// printf("%s\n",data.buf);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 if(data.cmd == 'L' && data.ack == 0)
  {
   printf("\n\033[33m用户名或密码错误:请重新输入!\033[0m\n\n");
   goto top;
  }
 if(data.cmd == 'L' && data.ack == 1)
  {
   printf("登陆成功\n");
   printf("%s\n",data.buf);
   
//   SSL_shutdown(ssl);
//    SSL_free(ssl);
//    close(sockclient);
//    SSL_CTX_free(ctx);
   return 1;
  }
 if(data.cmd == 'L' && data.ack == 2)
  {
   printf("\n\033[32m客户端最大连接数!\033[0m\n\n");
   exit(0);
  }
 return 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~显示客户端目录~~~~~~~~~~~~~~~~~~~
void Show(char temp[100])
{
 char command [2];
 if((strncpy(command,temp,1),*command)=='1'||(strncpy(command,temp,1),*command)=='2'||(strncpy(command,temp,1),*command)=='3')
  return;
 if(strncmp(temp,"cd",2)==0)
  {
   char dir[40]={'\0'};
   temp[strlen(temp)-1]='\0';
   strncpy(dir,(&(*temp)+3),strlen(&(*temp)+3));
  
   /*
   printf("%d%s",strlen((&(*temp)+3)),(&(*temp)+3));
   printf("%d%s",strlen(dir),dir);
   if(dir[strlen(dir)]=='\0')
    printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
   */
   
   chdir(dir);
   strcpy(temp,"ls");
  }
 system("clear");
 printf("\n\033[34m-----------------------------   \033[31mClient Files List   \033[34m----------------------------\033[0m\n");
 system(temp);
// printf("\033[34m*******************************************************************************\033[0m\n");
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~显示服务器目录~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 senddata(pack('S', " ", " ",  0, 9,1,tempuname));
 struct FilePackage data;
 if(recvdata(&data)==0)
  exit(0);
 if(data.cmd=='S')
  {
   printf("\033[34m-----------------------------   \033[31mServer Files List   \033[34m----------------------------\033[0m\n");
   printf("%s\n",data.buf);
   printf("\033[34m--------------------------------------------------------------------------------\033[0m\n");
  }
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
//~~~~~~~~~~~~~~~~~~~~~~~上传文件~~~~~~~~~~~~~~~~~~~~~~~~~
void * UpdateF(void *filename)
{
usleep(500);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
char *Files=(char *)filename;
 
int  sockclient;
struct sockaddr_in sockaddr1;
SSL_CTX *ctx;
SSL *ssl;

//printf("~2~ %s  %d\n",Files,strlen(Files));
if((sockclient=socket(AF_INET,SOCK_STREAM,0))==-1)
  {
   perror("socket"); 
   exit(0);
  }

 memset(&sockaddr1,0,sizeof(sockaddr1));
 sockaddr1.sin_family = AF_INET;
 sockaddr1.sin_addr.s_addr = inet_addr(ipaddr);
 sockaddr1.sin_port = htons(port);
 
 if(connect(sockclient,(struct sockaddr* )&sockaddr1,sizeof(sockaddr1))==-1)
  {
   perror("connect");
   exit(0);
  }

  //-----------------------------------------------------------------------
  /* SSL 库初始化 */
//  SSL_library_init();
//  OpenSSL_add_all_algorithms();
//  SSL_load_error_strings();
  ctx = SSL_CTX_new(SSLv23_client_method());
  if (ctx == NULL)
  {
    ERR_print_errors_fp(stdout);
    exit(1);
  }
 /* 基于 ctx 产生一个新的 SSL */
  ssl = SSL_new(ctx);
  SSL_set_fd(ssl, sockclient);
  /* 建立 SSL 连接 */

  if (SSL_connect(ssl) == -1)
    ERR_print_errors_fp(stderr);
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 int Fd;
 char buf[1025]={'\0'};
 int count=0;
 int temp=0;
 struct stat statbuf;
 struct FilePackage data;
 
 if(stat(Files,&statbuf)==-1)
  {
   perror("*");
   return 0;
  }
 if(!S_ISREG(statbuf.st_mode))
  perror("*");
  
  data=pack('U', " ", Files, statbuf.st_size , 9,0,tempuname);
  if((SSL_write(ssl,&data,sizeof(struct FilePackage)))==-1)
   perror("send login message:");

 if((SSL_read(ssl,&data,sizeof(struct FilePackage)))==-1)
 { 
  perror("recv login message:");
 }
 
 if(data.cmd == 'U' && data.ack == 1)
  {
   printf("服务器磁盘不足\n");
   return 0;
  }

 if(data.cmd == 'U' && data.ack == 0)
  {
   //do noting;
  }
 if((Fd=open(Files,O_RDONLY))==-1)
  perror("open: ");
// printf("~3~ %s  %d\n",Files,strlen(Files));
 while((count=read(Fd,(void *)buf,1024))>0)
  {
//   int i=0;
//   buf[count]='\0';
//   printf("count~~~~~~~~~~~~~~~~~~%d   %d\n",count,temp++);
//   printf("%s\n",buf);
//   printf("%s",buf);
   data=pack('U', buf, Files, count , 2,count,tempuname);
   if((SSL_write(ssl,&data,sizeof(struct FilePackage)))==-1)
    perror("send login message:");
//   printf("~~~~~%s~~~~~~\n",Files);
    /*
   int i=0;
   for(;i<1024;++i)
    {
     printf("%c",data.buf[i]); 
    }
    */
  }
  

 data=pack('U', " ", Files, statbuf.st_size , 4,1,tempuname);
 if((SSL_write(ssl,&data,sizeof(struct FilePackage)))==-1)
   perror("send login message:");

 if((SSL_read(ssl,&data,sizeof(struct FilePackage)))==-1)
 { 
  perror("recv login message:");
 }
 if(data.cmd == 'U' && data.ack == 3)
  {
   printf("\n\033[31mUpdate Files over\033[0m\n");
  }
 
 data=pack('Q', " ", " ", 0 , 9,0,tempuname);
 if((SSL_write(ssl,&data,sizeof(struct FilePackage)))==-1)
   perror("send login message:"); 
 close(Fd);
 close(sockclient);
 return (void *)1;
}
//~~~~~~~~~~~~~~~~~~~~~~~下载文件~~~~~~~~~~~~~~~~~~~~~~~~~

void * DownloadF(void *filename)
{
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
char *Files=(char *)filename;
int  sockclient;
struct sockaddr_in sockaddr1;
SSL_CTX *ctx;
SSL *ssl;
usleep(500);
//printf("~2~ %s  %d\n",Files,strlen(Files));
if((sockclient=socket(AF_INET,SOCK_STREAM,0))==-1)
  {
   perror("socket"); 
   exit(0);
  }
 memset(&sockaddr1,0,sizeof(sockaddr1));
 sockaddr1.sin_family = AF_INET;
 sockaddr1.sin_addr.s_addr = inet_addr(ipaddr);
 sockaddr1.sin_port = htons(port);
 
 if(connect(sockclient,(struct sockaddr* )&sockaddr1,sizeof(sockaddr1))==-1)
  {
   perror("connect");
   exit(0);
  }
  //-----------------------------------------------------------------------
 ctx = SSL_CTX_new(SSLv23_client_method());
 /* 基于 ctx 产生一个新的 SSL */
  ssl = SSL_new(ctx);
  SSL_set_fd(ssl, sockclient);
  /* 建立 SSL 连接 */
  if (SSL_connect(ssl) == -1)
    ERR_print_errors_fp(stderr);
//  else
//  {
//    printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
//    ShowCerts(ssl);
//  }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 int Fd;
 char buf[1024];
 int count=0;
 int temp=0;
 struct statfs statfsbuf;
 struct FilePackage data;
 struct stat statbuf;
 if(stat(Files,&statbuf)==0)
  {
   printf("文件重名\n");
   return 0;
  }

 data=pack('D', " ", Files, 0 , 9,1,tempuname);
 if((SSL_write(ssl,&data,sizeof(struct FilePackage)))==-1)
   perror("send login message:"); 
 if((SSL_read(ssl,&data,sizeof(struct FilePackage)))==-1)
 { 
  perror("recv login message:");
 }
 if(data.cmd == 'D' && data.ack == 0)
  {
   statfs("./",&statfsbuf);
   if((statfsbuf.f_bsize*statfsbuf.f_bfree)<=data.filesize)
    {
     printf("\033[31m磁盘空间不足\033[0m\n");
     return 0;
    }
  }
 if(data.cmd == 'D' && data.ack == 8)
  {
   printf("\033[33mNo such file or directory\033[0m\n");
   return 0;
  }
 if((Fd=open(Files,O_RDWR|O_CREAT,0777))==-1)
  perror("open: ");
// printf("\033[33mStart Download Files\033[0m\n");
 if(SSL_read(ssl,&data,sizeof(struct FilePackage))==-1)
  {
   perror("read error:\n");
  }
 while(data.ack==2)
  {
   count=data.filesize;
   if(write(Fd,data.buf,count)==-1)
   {
    perror("wirte error:\n"); 
   }
   if(SSL_read(ssl,&data,sizeof(struct FilePackage))==-1)
   {
    perror("read error:\n");
   }
  }
 if(data.ack==4)
   { 
     printf("\033[31mDownload Files over\033[0m\n");
     data=pack('D', " ", Files, 0 , 3,1,tempuname);
     if((SSL_write(ssl,&data,sizeof(struct FilePackage)))==-1)
      perror("send login message:"); 
      
     data=pack('Q', " ", " ", 0 , 9,0,tempuname);
     if((SSL_write(ssl,&data,sizeof(struct FilePackage)))==-1)
      perror("send login message:"); 
     close(sockclient);
     close(Fd);
    }

 return (void *)1;
}

//~~~~~~~~~~~~~~~~~~~~~~~主菜单~~~~~~~~~~~~~~~~~~~~~~~~~~~
void mainMenu()
{
 char temp[100];
 char command [2];
 char Files[100];
 char Files1[100];
 pthread_t pthreadt;
 strcpy(temp,"ls");
 while(1)
 {
  int count;
  int temp1;
  count=0;
  temp1=0;
  if(strncmp(temp,"\n",1)!=0)
   Show(temp);
  else
   goto top;
//   usleep(500);
//   printf("\033[34m*****************************\033[31mClient  console\033[34m*****************************\033[0m\n");
  printf("   \033[34m------------------------------\033[31mClient  console\033[34m-----------------------------\033[0m\n");
  printf("   \033[34m|\033[0m                1.Update Files   2.Download Files  3.Exit               \033[34m|\033[0m\n");
  printf("   \033[34m--------------   \033[36mUse \033[31mls \033[36mor \033[31mcd \033[36mto \033[31mdisplayer \033[36mand \033[31mchange dir   \033[34m--------------\033[0m\n");
  printf("  Please input the Client command:"); 
top:  fgets(temp,sizeof(temp),stdin);
  switch(strncpy(command,temp,1),*command)
  {
   case '1':
    {
     printf("\033[33mUpdate Files:\033[0m ");
     fgets(Files,sizeof(Files),stdin);
//     printf("%d\n",strlen(Files));
     Files[strlen(Files)-1]='\0';
     while(Files[count]!='\0' && Files[count]!='\n')
     {
      if(Files[count]==' ')
       {
        Files[count]='\0';
//        printf("~1~ %s\n",&Files[temp1]);
        pthread_create(&pthreadt,NULL,UpdateF,(void *)&Files[temp1]);
        temp1=count+1;
       }
       count++;
     }
     pthread_create(&pthreadt,NULL,UpdateF,(void *)&Files[temp1]);

     }

    strcpy(temp,"ls");
    break;
    
   case '2':
    {
     printf("\033[33mDownloadF Files:\033[0m ");
     fgets(Files1,sizeof(Files1),stdin);
     Files1[strlen(Files1)-1]='\0';
     while(Files1[count]!='\0' && Files1[count]!='\n')
     {
      if(Files1[count]==' ')
       {
        Files1[count]='\0';
        pthread_create(&pthreadt,NULL,DownloadF,(void *)&Files1[temp1]);
        temp1=count+1;
       }
       count++;
     }
     pthread_create(&pthreadt,NULL,DownloadF,(void *)&Files1[temp1]);
     }
    break;
    
   case '3':
    system("clear");
    
    exit(0);
    break;
  }
 }
}
//客户端的彻底的代码分析描述
int main(int argc,char *args[])
{
 //----------------------------------------------------------
   /* SSL 库初始化 */
  SSL_library_init();
  OpenSSL_add_all_algorithms();  //ssl的全部的函数算法
  SSL_load_error_strings();   //错误的处理
  ctx = SSL_CTX_new(SSLv23_client_method());
  if (ctx == NULL)
  {
    ERR_print_errors_fp(stdout);
    exit(1);
  }
  //----------------------------------------------------------
  strcpy(ipaddr,args[1]);  //第一个是ip的地址
 if((connectto(argc,args))!=1)
  exit(0);
 if(login(username,userpasswd)==0)
  {
   printf("login error");
   exit(0);
  }
 
 log();
 mainMenu();
 return 0;
}

你可能感兴趣的:(linux,struct,command,ssl,encryption,login)