⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mystar.c

📁 linux下上网的认证程序
💻 C
字号:
/*   Mystar is an 802.1x client tool for Linux, which is compatible with MentoSupplicant3.8 for Windows.   This file contains the main() function of mystar.*/#include "mystar.h"#include "global.h"#include "sendpacket.h"#include "myerr.h"#include "blog.h"/*   Note that: in this file, the global variables (defined without a leading "static")  from here to the beginning of the definition of main() are referenced by sendpacket.c ( we  reference them in the form of "extern ..." in sendpacket.c) *//* These info should be retrieved from mystar.conf */char         *m_name=NULL;//用户名char         *m_password=NULL;//密码int           m_authenticationMode=-1; //是哪种认证模式:0:标准 1:实达static char  *m_nic=NULL;//网卡static int    m_echoInterval= -1; //echo间隔, set to 0 to disable echostatic int    m_intelligentReconnect=-1; // 0:don't use it, 1: ues it.  NOTE: not supported NOW!!static char  *m_fakeAddress=NULL;  // or set to "123.45.67.89" etc./* These information should be worked out by initialization portion. */unsigned char         m_localMAC[6];//本机的MAC地址unsigned char         m_destMAC[6];//服务器的MAC地址.static unsigned char  m_ip[4];	//当前选择的网卡的IP地址static unsigned char  m_netmask[4];//当前选择的网卡的子网掩码static unsigned char  m_netgate[4];//当前选择的网卡的网关static unsigned char  m_dns1[4];   //当前选择的网卡的DNS/* 当前认证状态   0:未找到服务器                      1:已找到服务器,未通过用户名认证   2:已通过用户名认证,未通过MD5认证   3:已通过MD5认证,通网成功         */static volatile sig_atomic_t m_state=0;//当前认证状态ULONG_BYTEARRAY  m_serialNo;  //序列号,收到第一个有效的Authentication-Success-packet时初始化ULONG_BYTEARRAY  m_key;       //密码加密键值,在main()函数开始时初始化static void sig_intr(int signo); //do some cleanup work on exit with Ctrl+Cstatic void checkAndSetConfig(void); //configure related parametersint main(int argc, char* argv[]){   libnet_t *                l=NULL;   u_int32_t                 l_ip;   char                      l_errbuf[LIBNET_ERRBUF_SIZE];   struct libnet_ether_addr *l_ether_addr;   pcap_t             *p=NULL;   int                 p_fd;   fd_set              read_set;   char                filter_buf[256];   struct bpf_program  filter_code;   u_int32_t           p_netaddr,p_netmask;   struct pcap_pkthdr *pkt_hdr;   const u_char       *pkt_data;   char                p_errbuf[PCAP_ERRBUF_SIZE];   u_int16_t       offset;   int             msgLen;   char            msgBuf[256];   char           *pmsgBuf;   ULONG_BYTEARRAY uTemp;   int             isFirstPacketFromServer=1;   sigset_t        sigset_full,sigset_zero;   struct timespec timeout;   int packetCount_SentFindServer=0;   int packetCount_SentName=0;   int packetCount_SentPassword=0;   m_serialNo.ulValue = 0x1000002a;        //the initial serial number, a magic number!   checkAndSetConfig();   if((l=libnet_init(LIBNET_LINK, m_nic,l_errbuf))==NULL)       err_quit("libnet_init: %s\n", l_errbuf);   if((p=pcap_open_live(m_nic,65536,0, 500, p_errbuf))==NULL)      { err_msg("pcap_open_live: %s\n",p_errbuf); goto err1; }   p_fd=pcap_fileno(p); //we can pselect() it in the following code.   if((l_ether_addr=libnet_get_hwaddr(l))==NULL)      { err_msg("unable to get local mac address :%s\n",libnet_geterror(l)); goto err2; };   memcpy(m_localMAC,l_ether_addr,sizeof(m_localMAC));   if(m_fakeAddress==NULL)       {       	 if((l_ip=libnet_get_ipaddr4(l))==-1)           { err_msg("unable to get ip address--ingored... :%s\n",libnet_geterror(l)); l_ip=0; }         memcpy(m_ip,&l_ip,sizeof(m_ip));       }   else {}; //in this case , m_ip has been initialized in checkandSetConfig()   if(pcap_lookupnet(m_nic,&p_netaddr,&p_netmask,p_errbuf)==-1)     { err_msg("unable to get netmask--igored... %s\n",p_errbuf); p_netmask=0;}   memcpy(m_netmask,&p_netmask,sizeof(m_netmask));   InitializeBlog(m_ip,m_netmask,m_netgate,m_dns1); //see blog.c and bloc.h for details   //set the filter. Here I'm sure filter_buf is big enough.   snprintf(filter_buf,sizeof(filter_buf),FILTER_STR, m_localMAC[0],m_localMAC[1],        m_localMAC[2],m_localMAC[3],m_localMAC[4],m_localMAC[5],m_localMAC[6]);   if(pcap_compile(p, &filter_code,filter_buf, 0, p_netmask)==-1)     { err_msg("pcap_compile(): %s", pcap_geterr(p));  goto err2; }   if(pcap_setfilter(p, &filter_code)==-1)     { err_msg("pcap_setfilter(): %s", pcap_geterr(p)); goto err2; }   pcap_freecode(&filter_code); // avoid  memory-leak   (void)signal(SIGINT,sig_intr);  //We can exit with Ctrl+C   (void)sigfillset(&sigset_full);   (void)sigprocmask(SIG_BLOCK,&sigset_full,NULL); //block all signals.   //search for the server   beginAuthentication:      m_state=0;      (void)SendFindServerPacket(l); //the first time to search for server      packetCount_SentFindServer=1;      packetCount_SentName=0;      packetCount_SentPassword=0;   while(1)    {      (void)sigfillset(&sigset_full);      (void)sigdelset(&sigset_full,SIGINT);      FD_ZERO(&read_set);  FD_SET(p_fd, &read_set);      timeout.tv_sec =1;   timeout.tv_nsec =0; // 1 second      //wait with all signals(except SIGINT) blocked.      switch ( pselect(p_fd+1,&read_set,NULL,NULL,&timeout,&sigset_full) )      {          case -1: //Normally, this case should not happen since sig_intr() never returns!                   goto err2;          case 0:  //timed out                   switch(m_state)                   {                      case 0:                             if(++packetCount_SentFindServer>3)                                { puts("Restarting authenticaton!"); goto beginAuthentication; }                             (void)SendFindServerPacket(l);                             continue; //jump to next loop of while(1) to receive next packet                      case 1:                             if(++packetCount_SentName>3)                                { puts("Restarting authenticaton!"); goto beginAuthentication; }                             (void)SendNamePacket(l, pkt_data);                             continue;                      case 2:                            if(++packetCount_SentPassword>3)                                { puts("Restarting authenticaton!"); goto beginAuthentication; }                            (void)SendPasswordPacket(l, pkt_data);                             continue;                      default:                             goto err2;                   }      }      //Here return value of pselect must be 1      if((pcap_next_ex(p,&pkt_hdr,&pkt_data))!=1) continue;      //收到的第二个及其以后的有效packet的源MAC必须等于头次收到的有效分组的源MAC      if ((!isFirstPacketFromServer)&&(memcmp(m_destMAC,pkt_data+6,6)!=0)) continue;      //received a packet successfully. for convenience, SUPPOSE it's the RIGHT packet!! but maybe WRONG!!      //for example, we have NEVER vefified the length of packet, fancying the packet's length is 0x11 ?!       switch( pkt_data[0x12] )        //分析EAP包类型       {          case 0x01:        //表示请求                    switch( pkt_data[0x16] )                    {                        case 0x01:   //type 1,以用户名应答                                 if(m_state!=0) continue;                                 m_state=1;                                 fputs("@@ Server found, requesting user name...\n",stdout);                                 if (isFirstPacketFromServer) //获得服务器的MAC地址                                    { memcpy( m_destMAC, pkt_data+6, 6); isFirstPacketFromServer=0;}                                  ++packetCount_SentName;                                 (void)SendNamePacket(l, pkt_data);                                 break;                        case 0x04:   //type 4,挑战,以MD5计算得到的值应答                                 if(m_state!=1) continue;                                 m_state=2;                                 fputs("@@ User name valid, requesting password...\n",stdout);                                 ++packetCount_SentPassword;                                 (void)SendPasswordPacket(l, pkt_data);                                 break;                    }                    break;          case 0x03:         //认证成功                    if(m_state!=2) continue;                    m_state=3;                    fputs("@@ Password valid, authentication SUCCESS!!! :)\n",stdout);                    if (m_echoInterval<=0) goto done; //user has echo disabled                    //uTemp.ulValue = *(((u_long *)(pkt_data+0x9d)));                    offset=ntohs( *((u_int16_t*)(pkt_data+0x10)) );                    uTemp.ulValue = *((u_int32_t *)(pkt_data+(0x11+offset)-0x08));                    m_key.btValue[0] = Alog(uTemp.btValue[3]);                    m_key.btValue[1] = Alog(uTemp.btValue[2]);                    m_key.btValue[2] = Alog(uTemp.btValue[1]);                    m_key.btValue[3] = Alog(uTemp.btValue[0]);                    //unblock SIGINT, so we can exit with Ctrl+C                    (void)sigemptyset(&sigset_zero);                    (void)sigaddset(&sigset_zero,SIGINT);                    (void)sigprocmask(SIG_UNBLOCK,&sigset_zero,NULL);                    // continue echoing                    fputs("Keeping sending echo... \n",stdout);                    while(SendEchoPacket(l,pkt_data)==0) sleep(m_echoInterval);                    goto err2; //this should never happen.                    break;          case 0x04:        //认证失败(用户名或密码错误/不在上网时段内/重复上网等)                   if((m_state==0)||(m_state==3)) continue;                   m_state=0;                   msgLen=ntohs( *((u_int16_t*)(pkt_data+0x10)) )-10;                   if (msgLen>0)                      {                         if(msgLen>=(sizeof(msgBuf)-1)) msgLen=sizeof(msgBuf)-1;                         memset(msgBuf,'\0',sizeof(msgBuf));                         memcpy(msgBuf, pkt_data+0x1c, msgLen);                         pmsgBuf=msgBuf;                         //remove the leanding "\r\n" which seems alway to exist!                         if((msgLen>2)&&(msgBuf[0]==0xd)&&(msgBuf[1]==0xa)) pmsgBuf+=2;                      }                   else { pmsgBuf=""; } //这个估计是服务器告知静默或确认断网的包                   fprintf(stdout,"@@ Authenticaton failed!!! :(%s\n",pmsgBuf);                   (void)SendEndCertPacket(l);                   goto beginAuthentication;                   break; //should never come here      }// end switch    }// end while   done:         pcap_close(p); libnet_destroy(l);         return 0;   err2:         pcap_close(p);   err1:         libnet_destroy(l);         return 1;}static void checkAndSetConfig(void){   FILE  *fp;   char   buf[4096];   char  *p;   int   i,len;   static char name[32];   static char password[32];   static char nic[32];   static char fakeAddress[32];   int  intelligentReconnect=-1;   int  echoInterval=-1;   int  authenticationMode=-1;   //the check and anylysis against mystar.conf  *don't*  work perfectly.   //this may be improved in the later version.   if( (fp=fopen("/etc/mystar.conf","r"))==NULL ) err_quit("cannot open file /etc/mystar.conf ! check it.\n");   while(fgets(buf,sizeof(buf),fp)!=NULL)     {     	if( (buf[0]=='#') || (buf[0]=='\n') ) continue;     	len=strlen(buf); if(buf[len-1]=='\n') buf[len-1]='\0';     	if( ( (p=strchr(buf,'=')) == NULL) || (p==buf) )  continue;     	//the code above doesn't detect ALL the errors!! it should be improved in future.     	*p++='\0';     	for(i=0; i<strlen(buf); i++) buf[i]=tolower(buf[i]);     	if(strcmp(buf,"name")==0)     	   {  strncpy(name,p,sizeof(name)-1); name[sizeof(name)-1]=0;  m_name=name; }     	else if(strcmp(buf,"password")==0)     	   {              strncpy(password,p,sizeof(password)-1); password[sizeof(password)-1]=0;              m_password=password;     	    }     	else if(strcmp(buf,"authenticationmode")==0)     	   { authenticationMode=atoi(p);    m_authenticationMode=authenticationMode; }     	else if(strcmp(buf,"nic")==0)     	   {     	      for(i=0; i<strlen(p); i++) p[i]=tolower(p[i]);     	      strncpy(nic,p,sizeof(nic)-1); nic[sizeof(nic)-1]=0; m_nic=nic;     	    }     	else if(strcmp(buf,"echointerval")==0)     	        { echoInterval=atoi(p);   m_echoInterval=echoInterval;  }     	else if(strcmp(buf,"intelligentreconnect")==0)     	        { intelligentReconnect=atoi(p);  m_intelligentReconnect=intelligentReconnect; }     	else if(strcmp(buf,"fakeaddress")==0)     	       {     	       	  strncpy(fakeAddress,p,sizeof(fakeAddress)-1);     	       	  fakeAddress[sizeof(fakeAddress)-1]=0;     	       	  if( inet_pton(AF_INET,fakeAddress,m_ip)<=0 )     	       	     err_msg("invalid fakeAddress found in mystar.conf, ignored...\n");     	       	  else m_fakeAddress=fakeAddress;     	       }     	else continue;     }   if(ferror(fp)) err_quit("cannot read mystar.conf ! check it.\n");   fclose(fp);   if((m_name==NULL)||(m_name[0]==0)) err_quit("invalid name found in mystar.conf!\n");   if((m_password==NULL)||(m_password[0]==0)) err_quit("invalid password found in mystar.conf!\n");   if((m_authenticationMode<0)||(m_authenticationMode>1))      	 err_quit("invalid authenticationMode found in mystar.conf!\n");   if( (m_nic==NULL) || (strcmp(m_nic,"")==0) ||  (strcmp(m_nic,"any")==0) )       err_quit("invalid nic found in mystar.conf!\n");   if((m_echoInterval<0)||(m_echoInterval>100))      err_quit("invalid echo interval found in mystar.conf!\n" );   if((m_intelligentReconnect<0)||(m_intelligentReconnect>1))      err_quit("invalid intelligentReconnect found in mystar.conf!\n");   /*printf("m_name=%s\n",m_name);   printf("m_password=%s\n",m_password);   printf("m_nic=%s\n",m_nic);   printf("m_authenticationMode=%d\n",m_authenticationMode);   printf("m_echoInterval=%d\n",m_echoInterval);   printf("m_intelligentReconnect=%d\n",m_intelligentReconnect);//NOT supported now!!   printf("m_fakeAddress=%s\n",m_fakeAddress); */   //just set them to zero since they don't seem to be important.   memset(m_netgate,0,sizeof(m_netgate));  memset(m_dns1,0,sizeof(m_dns1));}static void sig_intr(int signo){   libnet_t *l=NULL;   char      l_errbuf[LIBNET_ERRBUF_SIZE];   if(m_state==3)      {          if((l=libnet_init(LIBNET_LINK, m_nic,l_errbuf))==NULL) _exit(0);          (void)SendEndCertPacket(l);          libnet_destroy(l);      }   _exit(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -