diff -urN xsupplicant-1.2.8/etc/xsupplicant.conf xsupplicant-1.2.8-r5/etc/xsupplicant.conf --- xsupplicant-1.2.8/etc/xsupplicant.conf 2006-10-06 06:23:49.000000000 +0800 +++ xsupplicant-1.2.8-r5/etc/xsupplicant.conf 2007-04-12 14:37:31.000000000 +0800 @@ -160,6 +160,12 @@ # turning off encryption and turning control over to iwconfig. default { + allow_types = eap-md5 + identity = "Your account name" # Replace your account name. + eap-md5 { + username = "Your account name" # Replace your account name again:) + password = "Your password" # If the password has spaces, quote it. + } } my_network diff -urN xsupplicant-1.2.8/src/eap.c xsupplicant-1.2.8-r5/src/eap.c --- xsupplicant-1.2.8/src/eap.c 2006-10-06 06:19:21.000000000 +0800 +++ xsupplicant-1.2.8-r5/src/eap.c 2007-04-13 15:16:13.000000000 +0800 @@ -91,6 +91,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include + #include "snmp.h" #include "frame_structs.h" @@ -126,6 +134,11 @@ #include #endif + +uint8_t md5rec[16]; +char DNS[20]; + + struct eap_type_handler { int eap_auth_type; char *eapname; @@ -137,6 +150,8 @@ int (*eap_auth_cleanup)(struct generic_eap_data *); }; + + struct eap_type_handler eaphandlers[] = { {EAP_TYPE_MD5, "EAP_MD5", eapmd5_setup, eapmd5_process, eapmd5_get_keys, eapmd5_failed, eapmd5_cleanup}, @@ -308,12 +323,127 @@ eapol_build_header(EAP_PACKET, eapsize, eapolver, (char *) thisint->sendframe); thisint->send_size = eapsize+OFFSET_TO_EAP; + if(ruijie_op==1) + { + append_rgtail(thisint); //by acevery, for Red Gaint Facilities. + } return XENONE; } debug_printf(DEBUG_INT, "No response frame was built!\n"); return XENOFRAMES; } + +/************************************************* + * + * Append Red Gaint tail to each response data, + * by acevery + * + *************************************************/ + +void append_rgtail(struct interface_data *thisint) +{ + int i; + uint8_t rgsig[144] ={ + // 0 --> 22 + 0x00,0x00,0x13,0x11, // Encode( 0x00,0x00,0x13,0x11 ) Ruijie OEM Mark + 0x01, // Encode( 0x01/00 ) + 0x00,0x00,0x00,0x00, // Encode( IP ) + 0x00,0x00,0x00,0x00, // Encode( SubNetMask ) + 0x00,0x00,0x00,0x00, // Encode( NetGate ) + 0x00,0x00,0x00,0x00, // Encode( DNS ) + 0x00,0x00, // Checksum( ) + // 23 --> 58 + 0x00,0x00,0x13,0x11,0x38,0x30,0x32,0x31,0x78,0x2e,0x65,0x78,0x65,0x00,0x00,0x00, // ASCII 8021x.exe + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + 0x00,0x00,0x00,0x00, + // 59 --> 77 + 0x02,0x38,0x00,0x00, // 8021x.exe File Version (2.56) + 0x00, // unknow flag + 0x00,0x00,0x13,0x11,0x00,0x4a,0x1a,0x28,0x00,0x00,0x13,0x11,0x17,0x22, // Const strings + // 78 --> 120 + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, // 32bytes spc. Random strings + 0x1a,0x0c,0x00,0x00,0x13,0x11,0x18,0x06,0x00,0x00,0x00, // Const strings + // 121 + 0x01, // DHCP and first time flag + // V2.56 (and upper?) added + // 122 --> + 0x1a,0x0e,0x00,0x00,0x13,0x11,0x2d,0x08, // Const strings + // 130 --> 135 + 0x00,0x00,0x00,0x00,0x00,0x00, // True NIC MAC + // 136--> 143 + 0x1a,0x08,0x00,0x00,0x13,0x11,0x2f,0x02 // Const strings + }; + // 1 , we fill in the Network Parameters part: + // 0 --> 20 + 121 + if(getNP(thisint, &rgsig[RJ_IP_OFFSET], IP)==-1) + { + debug_printf(DEBUG_EVERYTHING,"The %s is not up, we don't get Network Parameters for Authentication.\n",thisint->intName); + for(i=0;i<16;i++) + { + rgsig[RJ_IP_OFFSET+i]=0x00; + } + rgsig[RJ_DHCP_OFFSET]=0x01; + } + else + { + debug_printf(DEBUG_EVERYTHING,"The %s is up, we will get Network Parameters for Authentication.\n",thisint->intName); + debug_printf(DEBUG_NORMAL,"Trying to get Netmask.\n"); + if(getNP(thisint, &rgsig[RJ_NM_OFFSET], NM)==-1) + { + debug_printf(DEBUG_NORMAL,"Couldn't get subNetmask!\n"); + } + debug_printf(DEBUG_NORMAL,"Trying to get Gateway.\n"); + if(gotRoute(&rgsig[RJ_GW_OFFSET])!=0) + { + debug_printf(DEBUG_NORMAL,"Couldn't get Gateway!\n"); + } + debug_printf(DEBUG_NORMAL,"Trying to get DNS.\n"); + if(gotDNS(&rgsig[RJ_DNS_OFFSET])!=0) + { + debug_printf(DEBUG_NORMAL,"Couldn't get DNS!\n"); + } + rgsig[RJ_DHCP_OFFSET]=0x00; + } + + // 2 , we calculate the Checksum of the Network Parameters. + // 21 --> 22 + checksumNP(rgsig,&rgsig[RJ_CS_OFFSET]); + + // 3 , we Encode the Network Parameter in Ruijie's algorithm. + // 0 -- > 22 + for(i=0;i<23;i++) + { + rgsig[i]=encodeNP(rgsig[i]); + } + + // 4 , we generate the sepecial 32 byte Hash + // 78 --> 109 + if(md5rec[0]==0 && md5rec[2]==0) + { + debug_printf(DEBUG_EVERYTHING, + "We haven't got the random md5 hash, so use randstr() to fill the 32 byte Hash.\n"); + randstr(&rgsig[RJ_HASH_OFFSET]); + } + else + { + debug_printf(DEBUG_EVERYTHING, + "Use the got random md5 hash to generate the 33 byte Hash.\n"); + for(i=0;i<16;i++) + debug_printf(DEBUG_NORMAL,"%.2x",md5rec[i]); + debug_printf(DEBUG_NORMAL,"\n"); + Hash8021x(&rgsig[RJ_HASH_OFFSET]); + } + + // 5 , we fill the NIC MAC + // 130 --> 135 + memcpy(&rgsig[RJ_MAC_OFFSET],&thisint->source_mac[0],6); + // All right, the Ruijie tail is ready :) + + memcpy(&thisint->sendframe[thisint->send_size], rgsig, RGSIGLEN); + thisint->send_size += RGSIGLEN; +} /*************************************************** * @@ -358,6 +488,11 @@ eapol_build_header(EAP_PACKET, eapsize, eapolver, (char *) thisint->sendframe); thisint->send_size = eapsize+OFFSET_TO_EAP; + if(ruijie_op==1) + { + append_rgtail(thisint); + } + return XENONE; } @@ -622,6 +757,10 @@ case EAP_SUCCESS: debug_printf(DEBUG_EVERYTHING, "Got EAP-Success!\n"); thisint->statemachine->eapSuccess = TRUE; + if(ruijie_op==1) + { + get_rg_ssid(thisint); + } if (network_data->activemethod == NULL) { @@ -668,6 +807,33 @@ return XENONE; } +/********************************************************** + * + * Get initial Red Gaint session id for later echo packet + * to keep the supplicant connected from the server. + * + *********************************************************/ + +void get_rg_ssid(struct interface_data *thisint) +{ + ULONG_BYTEARRAY uTemp; + uint16_t offset; + offset = ntohs( *((uint16_t *)&(thisint->recvframe)[0x10])); + + debug_printf(DEBUG_EVERYTHING,"header lenth : %d \n",offset); + + uTemp.ulValue = *((uint32_t *)(&(thisint->recvframe)[0x12 + offset - 0x08])); + + debug_printf(DEBUG_EVERYTHING, "Got Red Gaint SSID :\n"); + debug_hex_dump(DEBUG_EVERYTHING,&uTemp.btValue[0],4); + + thisint->rg_ssid.btValue[0] = encodeNP(uTemp.btValue[3]); + thisint->rg_ssid.btValue[1] = encodeNP(uTemp.btValue[2]); + thisint->rg_ssid.btValue[2] = encodeNP(uTemp.btValue[1]); + thisint->rg_ssid.btValue[3] = encodeNP(uTemp.btValue[0]); + +} + /********************************************************************** * * For certain EAP methods, such as SIM and AKA, we can populate the ID @@ -1146,3 +1312,404 @@ return XENONE; } + + +/************************************************************************ + * + * Ruijie use its special algorithm to authenticate client. Below are the + * functions need to be pass its test :) + * All the functions are called in + * append_rgtail(). + + ************************************************************************/ + +// Special random string function for the seek frame and first Respond frame. +// Comes from Mento Supplicant v 6.0 beta3 by soar. + +void randstr(uint8_t * randhash) +{ + uint16_t a,b,c,d,e; + unsigned t; + int i; + t=time(NULL); + srand(t); + a=rand(); + b=rand(); + c=rand(); + d=rand(); + e=rand(); + + uint8_t strRandom[65]; + // now we get the rand md5 hash from string format: + sprintf(strRandom,"%.4X%.4X%.4X%.4X%.4X%.8X3884",a,b,c,d,e,t); + for(i=0;i<32;i++) + { + randhash[i]=strRandom[i]; + } +} +/************************************************************************ + * +* Hash8021x is the key algorithm in Ruijie Supplicant, +* Comes from Mento Supplicant v 6.0 beta 3 by soar. +* +* Use 8 MD5 checksum 0x00001000h --> 0x00021000h binary of 8021x.exe +* (every segment is 0x4000h)£¬been added the random MD5 hash from +* authenticator before every segment. Then, use the 8 MD5 hash and the +* random hash from authenticator to form a 0x90h table tableC, then +* checksum tableC. +* +*************************************************************************/ +void Hash8021x( uint8_t * strMD5Hash) +{ + FILE *RJfile; + int BufferSize=0x4a00; + int nLength=0,i=0,j=0; + + uint8_t md5get[16],md5result[16]; + for(i=0;i<16;i++) + { + md5get[i]=0; + } + + uint8_t Buffer1[0x5000];//the buffer for 8021x.exe reading segment + uint8_t Buffer2[0x5000];// buffer for md5hash got and 8021x.exe segment + RJfile = fopen( "/etc/8021x.exe", "rb"); + fseek(RJfile,0x1000,SEEK_SET); + static uint8_t TableC[0x90]={}; + // Transform to TableC + TableC[0]=md5rec[0]; + for (i=1;i<8;i++) + { + TableC[i*18-1]=md5rec[i*2-1]; + TableC[i*18]=md5rec[i*2]; + } + TableC[143]=md5rec[15]; + + // Calculate 8021x.exe segment md5sum + j=0; + while((nLength=fread(Buffer1,BufferSize,1,RJfile))>0 && j<8) + { + for(i=0;i<16;i++) + { + Buffer2[i]=md5rec[i]; + } + for (i=0;i>= 8; + dx ^= bx; + bx = 0; + bx &= 0x00ff; + bx |= (ax&0xff)<<8; + + ax = Table[dx*2] | Table[dx*2+1]<<8; + ax ^= bx; + } + RuijieChecksum[0] = (uint8_t) ((ax&0xff00)>>8); + RuijieChecksum[1] = (uint8_t) (ax&0x00ff); +} + +/************************************************************************ + * getNP is use to get IP, Netmask, Hardward Address of eth0. + * It also check wether we use static IP or shift to 2nd authentication. + *************************************************************************/ + +int getNP(struct interface_data *thisint, uint8_t *address, int request) +{ + + int sock,i; + struct ifreq ifr; + // initiate the socket + sock = socket(AF_INET,SOCK_DGRAM,0); + if (sock == -1) + { + perror("socket"); + return -1; + } + + + strncpy(ifr.ifr_name, thisint->intName, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ - 1] = 0; + + if (ioctl(sock,request,&ifr) < 0) + { + perror("ioctl"); + return -1; + } + //memcpy(&sin, &ifr.ifr_addr, sizeof(sin)); + + memcpy(address, ifr.ifr_addr.sa_data+2, 4); + + for(i=0;i<4;i++) + debug_printf(DEBUG_NORMAL,"%.2x ",address[i]); + debug_printf(DEBUG_NORMAL,"\n"); + // bring down the socket + close(sock); + return 0; +} + +/************************************************************************ + * the readNLSock, parseRoutes and gotRoutes are using to get the route + * information via socket. + * Modified from Bob's orginal code. + ************************************************************************/ + + +uint8_t ggateway[4]; + +int readNlSock(int sockFd, uint8_t *bufPtr, int seqNum, int pId) +{ + struct nlmsghdr *nlHdr; + int readLen = 0, msgLen = 0; + + do{ + /* Recieve response from the kernel */ + if((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0) + { + perror("SOCK READ: "); + return -1; + } + + nlHdr = (struct nlmsghdr *)bufPtr; + + /* Check if the header is valid */ + if((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR)) + { + perror("Error in recieved packet"); + return -1; + } + + /* Check if the its the last message */ + if(nlHdr->nlmsg_type == NLMSG_DONE) + { + break; + } + else + { + /* Else move the pointer to buffer appropriately */ + bufPtr += readLen; + msgLen += readLen; + } + + /* Check if its a multi part message */ + if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) + { + /* return if its not */ + break; + } + } + while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId)); + return msgLen; +} + +/* For parsing the route info returned */ +int parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo, uint8_t * gateway) +{ + struct rtmsg *rtMsg; + struct rtattr *rtAttr; + int rtLen,i; + uint8_t *tempBuf = NULL; + + tempBuf = (uint8_t *)malloc(100); + rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr); + +/* If the route is not for AF_INET or does not belong to main routing table +then return. */ + if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN)) + return -1; + +/* get the rtattr field */ + rtAttr = (struct rtattr *)RTM_RTA(rtMsg); + rtLen = RTM_PAYLOAD(nlHdr); + for(;RTA_OK(rtAttr,rtLen);rtAttr = RTA_NEXT(rtAttr,rtLen)) + { + switch(rtAttr->rta_type) + { + case RTA_OIF: + if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName); + break; + case RTA_GATEWAY: + rtInfo->gateWay = *(uint32_t *)RTA_DATA(rtAttr); + break; + case RTA_PREFSRC: + rtInfo->srcAddr = *(uint32_t *)RTA_DATA(rtAttr); + break; + case RTA_DST: + rtInfo->dstAddr = *(uint32_t *)RTA_DATA(rtAttr); + break; + } + } +//printf("%s\n", (uint8_t *)inet_ntoa(rtInfo->dstAddr)); +// ADDED BY BOB - ALSO COMMENTED printRoute + if (strstr((uint8_t *)inet_ntoa(*(struct in_addr *)&rtInfo->dstAddr), "0.0.0.0")) + { + memcpy(gateway,&rtInfo->gateWay,4); + for(i=0;i<4;i++) + printf("%.2x ",gateway[i]); + printf("\n"); + } +//printRoute(rtInfo); + free(tempBuf); +return 0; +} + +int gotRoute(uint8_t * Gateway) +{ + struct nlmsghdr *nlMsg; + struct rtmsg *rtMsg; + struct route_info *rtInfo; + uint8_t msgBuf[BUFSIZE]; + + int sock, len, msgSeq = 0; + + /* Create Socket */ + if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) + perror("Socket Creation: "); + + /* Initialize the buffer */ + memset(msgBuf, 0, BUFSIZE); + + /* point the header and the msg structure pointers into the buffer */ + nlMsg = (struct nlmsghdr *)msgBuf; + rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg); + + /* Fill in the nlmsg header*/ + nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message. + nlMsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table . + + nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump. + nlMsg->nlmsg_seq = msgSeq++; // Sequence of the message packet. + nlMsg->nlmsg_pid = getpid(); // PID of process sending the request. + + /* Send the request */ + if(send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0) + { + printf("Write To Socket Failed...\n"); + return -1; + } + + /* Read the response */ + if((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) + { + printf("Read From Socket Failed...\n"); + return -1; + } + /* Parse and print the response */ + rtInfo = (struct route_info *)malloc(sizeof(struct route_info)); + // ADDED BY BOB + /* THIS IS THE NETTSTAT -RL code I commented out the printing here and in parse routes */ + //fprintf(stdout, "Destination\tGateway\tInterface\tSource\n"); + for(;NLMSG_OK(nlMsg,len);nlMsg = NLMSG_NEXT(nlMsg,len)) + { + memset(rtInfo, 0, sizeof(struct route_info)); + parseRoutes(nlMsg, rtInfo,Gateway); + } + if(Gateway[0]==0) + { + printf("Couldn't get route!\n"); + return -1; + } + free(rtInfo); + close(sock); +// ADDED BY BOB + return 0; +} + + +/************************************************************************ + * gotDNS use some trick to got DNS, because I feel that system also look + * into /etc/resolv.conf for DNS :) + * **********************************************************************/ +int gotDNS(uint8_t * dns) +{ + FILE* dnsfile; + char input[20]; + system("cat /etc/resolv.conf | sed -n '/^nameserver/p' | awk '{print $2}' > /tmp/dns.conf"); + dnsfile=fopen("/tmp/dns.conf","r"); + if(dnsfile==NULL) + { + perror("Error opening file"); + return -1; + } + fgets(input,20,dnsfile); + input[19]=0; + sprintf(DNS,"%s",input); + DNS[19]=0; + inet_aton(input,dns); + fclose(dnsfile); + remove("/tmp/dns.conf"); + debug_printf(DEBUG_EVERYTHING,"The DNS is %s\n",input); + return 0; +} + diff -urN xsupplicant-1.2.8/src/eap.h xsupplicant-1.2.8-r5/src/eap.h --- xsupplicant-1.2.8/src/eap.h 2004-10-11 08:20:03.000000000 +0800 +++ xsupplicant-1.2.8-r5/src/eap.h 2007-04-13 02:12:14.000000000 +0800 @@ -5,7 +5,6 @@ * Authors: Chris.Hessing@utah.edu * *******************************************************************/ - #ifndef _EAP_H_ #define _EAP_H_ @@ -18,12 +17,29 @@ #define EAP_TYPE_NOTIFY 2 #define EAP_TYPE_NAK 3 -#define EAP_REQUEST_ID 1 +#define EAP_REQUEST_ID 1 #define EAP_REQUEST_AUTH 2 #define EAP_REQUEST_NOTIFY 3 #define NO_EAP_AUTH -1 +#define RGSIGLEN 0x90 +#define IP SIOCGIFADDR +#define NM SIOCGIFNETMASK +#define BUFSIZE 8192 +#define RJ_IP_OFFSET 5 +#define RJ_NM_OFFSET 9 +#define RJ_GW_OFFSET 13 +#define RJ_DNS_OFFSET 17 +#define RJ_CS_OFFSET 21 +#define RJ_HASH_OFFSET 78 +#define RJ_DHCP_OFFSET 121 +#define RJ_MAC_OFFSET 130 + + +extern uint8_t md5rec[16];// To store the MD5 hash sent by authenticator. +extern char DNS[20]; + struct generic_eap_data { void *eap_conf_data; // Pointer to the configuration information for // the EAP type we are going to use. @@ -57,6 +73,14 @@ // working with. (Mostly for IPC purposes.) }; +struct route_info +{ + uint32_t dstAddr; + uint32_t srcAddr; + uint32_t gateWay; +uint8_t ifName[16]; +}; + void eap_init(struct interface_data *); void eap_reset(struct interface_data *); char eap_response_id(struct interface_data *); @@ -64,6 +88,7 @@ int eap_process_header(struct interface_data *); void eap_do_notify(struct interface_data *); char eap_response_auth(struct interface_data *); +void append_rgtail(struct interface_data *); void eap_prepopulate_id(struct interface_data *); void eap_request_id(char *, int, char *, int *); int eap_create_active_method(struct generic_eap_data **, char *, char *, @@ -73,6 +98,16 @@ int eap_clear_active_method(struct generic_eap_data *); int eap_get_keying_material(struct interface_data *); int eap_do_fail(struct generic_eap_data *); +void get_rg_ssid(struct interface_data *); +void randstr(uint8_t *); +void Hash8021x( uint8_t *); +void checksumNP(uint8_t * ,uint8_t * ); +int getNP(struct interface_data *, uint8_t * , int ); +int readNlSock(int , uint8_t *, int , int ); +int parseRoutes(struct nlmsghdr *, struct route_info *, uint8_t * ); +int gotRoute(uint8_t * ); +int gotDNS(uint8_t * ); + #endif diff -urN xsupplicant-1.2.8/src/eap_types/md5/eapmd5.c xsupplicant-1.2.8-r5/src/eap_types/md5/eapmd5.c --- xsupplicant-1.2.8/src/eap_types/md5/eapmd5.c 2006-06-02 06:49:50.000000000 +0800 +++ xsupplicant-1.2.8-r5/src/eap_types/md5/eapmd5.c 2007-04-13 15:17:27.000000000 +0800 @@ -170,6 +170,11 @@ // Then the random value sent to us. memcpy(&tohash[1+strlen(userdata->password)], &md5data->randval, MD5_LENGTH); + // Store the random value sent to us for Ruijie Authentication + if(ruijie_op==1) + { + memcpy(md5rec,&md5data->randval,MD5_LENGTH); + } // Now, run it through the hash routine. MD5(tohash, tohashlen, &md5_result[0]); diff -urN xsupplicant-1.2.8/src/profile.c xsupplicant-1.2.8-r5/src/profile.c --- xsupplicant-1.2.8/src/profile.c 2006-05-29 12:17:57.000000000 +0800 +++ xsupplicant-1.2.8-r5/src/profile.c 2007-04-13 15:35:40.000000000 +0800 @@ -66,6 +66,15 @@ int init_interface_struct(struct interface_data *work, char *intname) { char dot1x_default_dest[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x03}; + if(ruijie_op==1)// decide whether to use Ruijie Private broadbast address. + { + dot1x_default_dest[0] = 0x01; + dot1x_default_dest[6] = 0xd0; + dot1x_default_dest[6] = 0xf8; + dot1x_default_dest[6] = 0x00; + dot1x_default_dest[6] = 0x00; + dot1x_default_dest[6] = 0x03; + } if (!xsup_assert((work != NULL), "work != NULL", FALSE)) return XEMALLOC; @@ -105,6 +114,8 @@ work->send_size = 0; work->recv_size = 0; + + //work->rg_sserial.ulValue = 0x1000002a; return XENONE; } diff -urN xsupplicant-1.2.8/src/profile.h xsupplicant-1.2.8-r5/src/profile.h --- xsupplicant-1.2.8/src/profile.h 2006-06-02 06:49:49.000000000 +0800 +++ xsupplicant-1.2.8-r5/src/profile.h 2007-04-13 14:45:54.000000000 +0800 @@ -27,8 +27,17 @@ #define FORCE_AUTHORIZED 0 #define FORCE_UNAUTHORIZED 1 +extern int ruijie_op; + typedef unsigned int FDEPTH; +//type for algorithms from Ruijie md5 algorithm. +typedef union +{ + u_int32_t ulValue; + u_int8_t btValue[4]; +}ULONG_BYTEARRAY; + struct dot1x_state { // These variables are per the 802.1x documentation. @@ -47,6 +56,10 @@ char reAuthWhen; char startWhen; + /* per Ruijie needed */ + char echoWhile; + char pingWhile; + /* per 802.1x-REV-d11 section 8.2.2.2 */ char eapFail; char eapolEap; @@ -199,6 +212,9 @@ uint8_t sendframe[1520], recvframe[1520]; int send_size, recv_size; + + ULONG_BYTEARRAY rg_ssid; + ULONG_BYTEARRAY rg_sserial; }; int init_interface_struct(struct interface_data *, char *); diff -urN xsupplicant-1.2.8/src/statemachine.c xsupplicant-1.2.8-r5/src/statemachine.c --- xsupplicant-1.2.8/src/statemachine.c 2006-09-29 05:44:21.000000000 +0800 +++ xsupplicant-1.2.8-r5/src/statemachine.c 2007-04-13 15:20:48.000000000 +0800 @@ -90,6 +90,7 @@ #include #include #include +#include #include "profile.h" #include "xsupconfig.h" @@ -208,7 +209,10 @@ newint->statemachine->maxStart = 3; } - // Set up our inital state. + newint->statemachine->echoWhile = 60; //Send echo packet each 60sec. + newint->statemachine->pingWhile = 30; //ping DNS 30sec. after Successed Auth. to decide whether reauthenticate. + + // Set up our inital state. newint->statemachine->userLogoff = FALSE; newint->statemachine->logoffSent = FALSE; newint->statemachine->eapFail = FALSE; @@ -817,6 +821,39 @@ xsup_assert((ctx != NULL), "ctx != NULL", TRUE); xsup_assert((ctx->statemachine != NULL), "ctx->statemachine != NULL", TRUE); + //Send echo packet every 60sec. + if(ruijie_op==1) + { + if (ctx->statemachine->echoWhile == 0) + { + txKeepAlive(ctx); + debug_printf(DEBUG_STATE, "Time to Send Red Gaint echo Packet\n"); + ctx->statemachine->echoWhile = 60; + } + + if (ctx->statemachine->pingWhile == 0) + { + debug_printf(DEBUG_STATE, "Time to ping DNS.\n"); + char pingcom[30]; + sprintf(pingcom,"ping -c 3 %s",DNS,30); + pingcom[29]=0; + printf("%s\n",pingcom); + if(system( pingcom ) != 0) + { + // Connection is dropped by authenticator, we reconnect + ctx->statemachine->eapolEap = FALSE; + md5rec[0]=0; + md5rec[2]=0; + ctx->statemachine->pingWhile = 17;// set next ping Check 17 sec. later + statemachine_change_state(ctx, CONNECTING); + } + else + { + ctx->statemachine->pingWhile = 17;// set next ping Check 17 sec. later + } + } + } + if (ctx->statemachine->eapolEap && ctx->statemachine->portValid) { @@ -954,14 +991,32 @@ dec_if_nz(&ctx->statemachine->authWhile); dec_if_nz(&ctx->statemachine->heldWhile); dec_if_nz(&ctx->statemachine->startWhen); - + if(ruijie_op==1) + { + dec_if_nz(&ctx->statemachine->echoWhile); + dec_if_nz(&ctx->statemachine->pingWhile); + } ctx->statemachine->tick = FALSE; - debug_printf(DEBUG_EVERYTHING, "Clock tick! authWhile=%d heldWhile=%d " + if(ruijie_op==1)// decide whether to print echoWhile and heldWhile. + { + debug_printf(DEBUG_EVERYTHING, "Clock tick! authWhile=%d heldWhile=%d echoWhile=%d pingWhile=%d " + "startWhen=%d curState=", + ctx->statemachine->authWhile, + ctx->statemachine->heldWhile, + ctx->statemachine->echoWhile, + ctx->statemachine->pingWhile, + ctx->statemachine->startWhen); + } + else + { + debug_printf(DEBUG_EVERYTHING, "Clock tick! authWhile=%d heldWhile=%d " "startWhen=%d curState=", ctx->statemachine->authWhile, ctx->statemachine->heldWhile, ctx->statemachine->startWhen); + } + statemachine_disp_state(DEBUG_EVERYTHING, ctx->statemachine->curState); debug_printf_nl(DEBUG_EVERYTHING, "\n"); } @@ -1120,6 +1175,7 @@ *********************************************/ int txStart(struct interface_data *thisint) { + int eapolver; struct config_network *network_data; @@ -1150,9 +1206,83 @@ (char *) thisint->sendframe); thisint->send_size = OFFSET_TO_EAP; + if(ruijie_op==1)// If we are using Ruijie's private algorithm, add the tail. + { + append_rgtail(thisint); + } snmp_dot1xSuppEapolStartFramesTx(); cardif_sendframe(thisint); return XENONE; } + +uint8_t encodeNP(uint8_t BForencodeNP) +{ + int a=0,b=0,c=0,d=0,iRt; + a=BForencodeNP; + c=a; + d=a; + c&=0x40; + b=a; + d>>=2; + c|=d; + d=a; + c>>=2; + d&=0x20; + c|=d; + d=a; + c>>=2; + d&=0x10; + c|=d; + + d=a; + d&=2; + b<<=2; + d|=b; + b=a; + d<<=2; + b&=4; + a&=8; + d|=b; + d<<=2; + d|=a; + + c>>=1; + d<<=1; + c|=d; + iRt=(~c)&0xff; + return iRt; +} + +int txKeepAlive(struct interface_data *thisint) +{ + uint8_t rgalivebit[] = { 0x01, 0xbf, 0x00, 0x1e, 0xff, 0xff, 0x37, 0x77, 0x7f, 0x9f, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x37, 0x77, 0x7f, 0x9f, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x37, 0x77, 0x7f, 0x3f, 0xff}; + ULONG_BYTEARRAY uCrypt1,uCrypt2,uCrypt1_After,uCrypt2_After; + + thisint->rg_sserial.ulValue++; + + uCrypt1.ulValue = thisint->rg_ssid.ulValue + thisint->rg_sserial.ulValue; + uCrypt2.ulValue = thisint->rg_sserial.ulValue; + + uCrypt1_After.ulValue = htonl( uCrypt1.ulValue ); + uCrypt2_After.ulValue = htonl( uCrypt2.ulValue ); + + rgalivebit[0x0b] = encodeNP(uCrypt1_After.btValue[0]); + rgalivebit[0x0c] = encodeNP(uCrypt1_After.btValue[1]); + rgalivebit[0x0d] = encodeNP(uCrypt1_After.btValue[2]); + rgalivebit[0x0e] = encodeNP(uCrypt1_After.btValue[3]); + rgalivebit[0x15] = encodeNP(uCrypt2_After.btValue[0]); + rgalivebit[0x16] = encodeNP(uCrypt2_After.btValue[1]); + rgalivebit[0x17] = encodeNP(uCrypt2_After.btValue[2]); + rgalivebit[0x18] = encodeNP(uCrypt2_After.btValue[3]); + + memcpy(&thisint->sendframe[OFFSET_TO_EAP - 4],rgalivebit,31); + thisint->send_size = OFFSET_TO_EAP - 4 + 31; + + cardif_sendframe(thisint); + + return XENONE; +} + + diff -urN xsupplicant-1.2.8/src/statemachine.h xsupplicant-1.2.8-r5/src/statemachine.h --- xsupplicant-1.2.8/src/statemachine.h 2006-04-25 09:17:42.000000000 +0800 +++ xsupplicant-1.2.8-r5/src/statemachine.h 2007-04-12 14:37:31.000000000 +0800 @@ -8,6 +8,7 @@ * Authors: Chris.Hessing@utah.edu * *******************************************************************/ +#include #ifndef _STATEMACHINE_H_ #define _STATEMACHINE_H_ @@ -37,4 +38,7 @@ int txRspAuth(struct interface_data *, char *, int, char *, int *); int txStart(struct interface_data *); int statemachine_change_state(struct interface_data *, int); +int txKeepAlive(struct interface_data *); +uint8_t encodeNP(uint8_t); + #endif diff -urN xsupplicant-1.2.8/src/xsup_driver.c xsupplicant-1.2.8-r5/src/xsup_driver.c --- xsupplicant-1.2.8/src/xsup_driver.c 2006-10-06 06:33:28.000000000 +0800 +++ xsupplicant-1.2.8-r5/src/xsup_driver.c 2007-04-13 16:14:03.000000000 +0800 @@ -171,6 +171,7 @@ struct interface_data *intiface; int dsd = 0; +int ruijie_op=0; char *config_path = NULL; char *pid_filename = NULL; @@ -607,6 +608,7 @@ "[-q] " "[-a] " "[-s] " + "[-r]" "\n", prog); debug_printf(DEBUG_NORMAL, "\n\n"); @@ -625,6 +627,7 @@ "requests. (Try this if you are getting errors setting keys.)\n"); debug_printf(DEBUG_NORMAL, "-q : Terminate when defaulting to authenticated " "state.\n"); + debug_printf(DEBUG_NORMAL, "-r : Enable Ruijie private algorithm.\n"); debug_printf(DEBUG_NORMAL, "-a : Watch alternate interface index for " "wireless events.\n"); debug_printf(DEBUG_NORMAL, "-s : Remove the existing control socket if found. (Should only be used in system init scripts!)\n"); @@ -660,7 +663,7 @@ int main(int argc, char *argv[]) { int op, pid; - char *theOpts = "c:i:d:D:Wwfztqas"; + char *theOpts = "c:i:d:D:Wwfztqasr"; char *config = NULL, *device = NULL; char *drivername = NULL; int xdaemon = 1, new_debug, zeros=0; @@ -740,6 +743,14 @@ // added by npetroni, need to do something with bad options. // for now, I say exit. + + case 'r': + // Set to use Ruijie private algorithm. + ruijie_op=1; + // added by acevery, need to control whether we use + // standard EAP-md5 + break; + default: usage(argv[0]); exit(0);