Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

evapacket.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2004 by yunfan                                          *
00003  *   yunfan_zg@163.com                                                     *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020  
00021 #include "evapacket.h"
00022 #ifdef _WIN32
00023 #include <winsock.h>
00024 #else
00025 #include <arpa/inet.h>
00026 #endif
00027 #include <string.h>
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 #include "evacrypt.h"
00031 
00032 unsigned char Packet::iniKey[16] = {
00033                         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
00034                         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
00035                         };
00036                         
00037 int Packet::qqNum = -1;
00038 bool Packet::mIsUDP = true;
00039 unsigned char *Packet::sessionKey = NULL;
00040 unsigned char *Packet::passwordKey = NULL;
00041 unsigned char *Packet::fileSessionKey = NULL;
00042 unsigned char *Packet::loginToken= NULL;
00043 int Packet::loginTokenLength = 0;
00044 unsigned char *Packet::clientKey= NULL;
00045 int Packet::clientKeyLength = 0;
00046 
00047 unsigned char *Packet::fileAgentKey = NULL;
00048 unsigned char *Packet::fileAgentToken = NULL;
00049 int Packet::fileAgentTokenLength = 0;
00050 
00051 unsigned char *Packet::fileShareToken = NULL;
00052 
00053 Packet::Packet(const short version, const short command, const short sequence)
00054 {
00055         this->version = version;
00056         this->command = command;
00057         this->sequence = sequence;
00058 }
00059 
00060 Packet::Packet(unsigned char *buf, int *len)
00061 {
00062         int pos;
00063         // if it's not UDP, must be TCP
00064         if(!mIsUDP)     
00065                 pos=3;
00066         else
00067                 pos = 1;
00068         
00069         short tmp;
00070         
00071         memcpy(&tmp, buf+pos, 2);
00072         version = ntohs(tmp);
00073         pos+=2;
00074         
00075         memcpy(&tmp, buf+pos, 2);
00076         command = ntohs(tmp);
00077         pos+=2;
00078         
00079         memcpy(&tmp, buf+pos, 2);
00080         sequence = ntohs(tmp);
00081         pos+=2;
00082         
00083         (*len)=(*len)-pos;
00084         memcpy(buf, buf+pos, *len);
00085 }
00086 
00087 Packet::Packet(const Packet &rhs)
00088 {
00089         *this = rhs;
00090 }
00091 
00092 Packet::~Packet()
00093 {
00094 }
00095 
00096 bool Packet::operator ==( const Packet &rhs) const
00097 {
00098         return (command == rhs.getCommand()) && (sequence == rhs.getSequence());
00099 }
00100 
00101 Packet &Packet::operator=(const Packet &rhs)
00102 {
00103         this->version = rhs.getVersion();
00104         this->command = rhs.getCommand();
00105         this->sequence = rhs.getSequence();
00106         this->mIsUDP = rhs.isUDP();
00107         return *this;   
00108 }
00109 
00110 const int Packet::hashCode() 
00111 {
00112         return ((int)sequence << 16) | command;
00113 }
00114 
00115 void Packet::setSessionKey(const unsigned char *skey)
00116 {
00117         if(!sessionKey)
00118                 sessionKey = new unsigned char[QQ_KEY_LENGTH];
00119         memcpy(sessionKey, skey, QQ_KEY_LENGTH);
00120         fprintf(stderr,"session key set!\n");
00121 }
00122 
00123 void Packet::setPasswordKey(const unsigned char* pkey)
00124 {
00125         if(!passwordKey) 
00126                 passwordKey = new unsigned char[QQ_KEY_LENGTH];
00127         memcpy(passwordKey, pkey, QQ_KEY_LENGTH);
00128         fprintf(stderr, "password key set!\n");
00129 }
00130 
00131 void Packet::setFileSessionKey(const unsigned char* fskey)
00132 {
00133         if(!fileSessionKey) 
00134                 fileSessionKey = new unsigned char[QQ_KEY_LENGTH];
00135         memcpy(fileSessionKey, fskey, QQ_KEY_LENGTH);
00136         fprintf(stderr, "file session key set!\n");
00137 }
00138 
00139 void Packet::setLoginToken(const unsigned char *token, const int length)
00140 {
00141         if(!loginToken)
00142                 loginToken = new unsigned char[length];
00143         memcpy(loginToken, token, length);
00144         loginTokenLength = length;
00145         fprintf(stderr, "login token set!\n");  
00146 }
00147 
00148 void Packet::setClientKey(const unsigned char *ckey, const int length)
00149 {
00150         if(!clientKey)
00151                 clientKey = new unsigned char[length];
00152         memcpy(clientKey, ckey, length);
00153         clientKeyLength = length;
00154         fprintf(stderr, "client key set!\n");
00155 }
00156 
00157 void Packet::setFileAgentKey(const unsigned char *key)
00158 {
00159         if(!fileAgentKey)
00160                 fileAgentKey = new unsigned char[QQ_KEY_LENGTH];
00161         memcpy(fileAgentKey, key, 16);
00162         fprintf(stderr, "file agent key set!\n");
00163         for(int i=0; i<16; i++){
00164                 //if(!(i%8)) printf("\n%d: ",i);
00165                 char t = fileAgentKey[i];
00166                 printf("%2x", (unsigned char)t);
00167         }
00168         printf("\n");
00169 }
00170 
00171 void Packet::setFileAgentToken(const unsigned char *token, const int length)
00172 {
00173         if(!fileAgentToken)
00174                 fileAgentToken = new unsigned char[length];
00175         memcpy(fileAgentToken, token, length);
00176         fileAgentTokenLength = length;
00177         fprintf(stderr, "file agent token set!\n");     
00178         for(int i=0; i<length; i++){
00179                 //if(!(i%8)) printf("\n%d: ",i);
00180                 char t = fileAgentToken[i];
00181                 printf("%2x", (unsigned char)t);
00182         }
00183         printf("\n");
00184 }
00185 
00186 void Packet::setFileShareToken(const unsigned char *token)
00187 {
00188         if(!fileShareToken)
00189                 fileShareToken = new unsigned char[24];
00190         memcpy(fileShareToken, token, 24);
00191         fprintf(stderr, "file share token set!\n");
00192 }
00193 
00194 // this will be called just right before sending in OutPacket::fill method
00195 void Packet::clearAllKeys()
00196 {
00197         if(sessionKey) delete [] sessionKey;
00198         if(passwordKey) delete [] passwordKey;
00199         if(fileSessionKey) delete [] fileSessionKey;
00200         if(loginToken) delete [] loginToken;
00201         if(clientKey) delete [] clientKey;
00202         if(fileAgentKey) delete [] fileAgentKey;
00203         if(fileAgentToken) delete [] fileAgentToken;
00204         if(fileShareToken) delete [] fileShareToken;
00205         
00206         // force them to NULL now
00207         sessionKey = NULL;
00208         passwordKey = NULL;
00209         fileSessionKey = NULL;
00210         loginToken = NULL;
00211         loginTokenLength = 0;
00212         clientKey = NULL;
00213         clientKeyLength = 0;
00214         fileAgentKey = NULL;
00215         fileAgentToken = NULL;
00216         fileAgentTokenLength = 0;
00217         fileShareToken = NULL;
00218 }
00219 
00220 /* =========================================================== */
00221 
00222 // OutPacket starts here
00223 short OutPacket::startSequenceNum = 5;   // could be any random number
00224 
00225 OutPacket::OutPacket(const short command, const bool needAck) :
00226         Packet(QQ_CLIENT_VERSION, command, ((startSequenceNum++)%0xffff))
00227 {
00228         this->mNeedAck = needAck;
00229         resendCount = 5;
00230 }
00231 
00232 OutPacket::OutPacket(const OutPacket &rhs) 
00233         : Packet(rhs)
00234 {
00235         mNeedAck = rhs.needAck();
00236         resendCount = rhs.getResendCount();
00237 }
00238 
00239 bool OutPacket::fill(unsigned char *buf, int *len) 
00240 {
00241         int headerLen = 0, bodyLen=0, encryptedLen = 0;
00242         unsigned char *bodyBuf;
00243         unsigned char *encrypted;
00244         bodyBuf   = (unsigned char *)malloc(MAX_PACKET_SIZE* sizeof(unsigned char));
00245         encrypted = (unsigned char *)malloc(MAX_PACKET_SIZE * sizeof(unsigned char));
00246         
00247         headerLen = putHead(buf);       
00248         bodyLen   = putBody(bodyBuf);
00249         encryptedLen = bodyLen;
00250         encryptBody(bodyBuf, bodyLen, encrypted, &encryptedLen);
00251         
00252         memcpy(buf+headerLen, encrypted, encryptedLen);
00253         
00254         buf[ headerLen + encryptedLen ] = QQ_PACKET_TAIL;
00255         (*len) = headerLen + encryptedLen + 1;
00256         
00257         if(!isUDP()) { 
00258                 short tmp2 = htons(*len);
00259                 memcpy(buf, &tmp2, 2);
00260         }
00261         free(bodyBuf);
00262         free(encrypted);
00263         return true;
00264 }
00265 
00266 OutPacket &OutPacket::operator=( const OutPacket &rhs)
00267 {
00268         *((Packet*)this) = (Packet)rhs;
00269         mNeedAck = rhs.needAck();
00270         resendCount = rhs.getResendCount();
00271         return *this;
00272 }
00273 
00274 int OutPacket::putBody(unsigned char *buf)
00275 {
00276         fprintf(stderr, "In OutPacket\n"); 
00277         buf[0]=0; 
00278         return 0;
00279 }
00280 
00281 int OutPacket::putHead(unsigned char *buf) 
00282 {
00283         int pos=0;
00284         if(!isUDP()){
00285                 buf[0]=buf[1]=0;
00286                 pos+=2;
00287         }
00288         buf[pos++]=(unsigned char)QQ_PACKET_TAG;
00289         
00290         short tmp = htons(version);
00291         memcpy(buf+pos, &tmp, 2);
00292         pos+=2; 
00293         
00294         tmp = htons(command);
00295         memcpy(buf+pos, &tmp, 2);
00296         pos+=2; 
00297 
00298         tmp = htons(sequence);
00299         memcpy(buf+pos, &tmp, 2);
00300         pos+=2; 
00301         
00302         int id = htonl(getQQ());
00303         memcpy(buf+pos, &id, 4);
00304         pos+=4;
00305                 
00306         return pos;
00307 }
00308 
00309 void OutPacket::encryptBody(unsigned char *b, int length, 
00310                             unsigned char *body, int *bodyLen) 
00311 {
00312         switch(command){
00313         case QQ_CMD_REQUEST_LOGIN_TOKEN:
00314         case QQ_CMD_LOGIN:  
00315                 *bodyLen = length;
00316                 memcpy(body, b, length);
00317                 break;
00318         default:{
00319                 unsigned char * sessionKey = getSessionKey();
00320                 if(sessionKey == NULL) {     
00321                         fprintf(stderr, "OutPacket->encryptBody: sessionkey not set yet, set encrypted length to 0\n");
00322                         *bodyLen = 0;
00323                         return;
00324                 } 
00325                 EvaCrypt::encrypt(b, length, sessionKey, body, bodyLen); 
00326                 }
00327         }
00328 }
00329 
00330 /* =========================================================== */
00331 
00332 // InPacket Class starts here
00333 
00334 InPacket::InPacket( )
00335         : decryptedBuf(NULL)
00336 {
00337 }
00338 
00339 InPacket::InPacket( unsigned char *buf, int len)
00340         : Packet(buf, &len),
00341         bodyLength(0)
00342 {
00343         decryptedBuf = (unsigned char*)malloc(MAX_PACKET_SIZE * sizeof(unsigned char));
00344         decryptBody(buf, len - QQ_TAIL_LENGTH);
00345 }
00346 
00347 InPacket::InPacket(const InPacket &rhs)
00348         : Packet(rhs)
00349 {
00350         bodyLength = rhs.getLength();
00351         decryptedBuf = (unsigned char*)malloc(bodyLength * sizeof(unsigned char));
00352         memcpy(decryptedBuf, rhs.getBody(), bodyLength);
00353 }
00354 
00355 InPacket::~InPacket()
00356 {
00357         delete decryptedBuf;
00358 }
00359 
00360 InPacket &InPacket::operator=( const InPacket &rhs)
00361 {
00362         *((Packet*)this) = (Packet)rhs;
00363         bodyLength = rhs.getLength();
00364         if(!decryptedBuf){
00365                 delete decryptedBuf;
00366                 decryptedBuf = new unsigned char[bodyLength];
00367         }
00368         memcpy(decryptedBuf, rhs.getBody(), bodyLength);
00369         return *this;
00370 }
00371 
00372 void InPacket::decryptBody(unsigned char * buf, int len)
00373 {
00374         int ret;
00375         bodyLength = MAX_PACKET_SIZE;
00376         
00377         unsigned char * passwordKey = getPasswordKey();
00378         unsigned char * sessionKey = getSessionKey();
00379         
00380         if(command == QQ_CMD_REQUEST_LOGIN_TOKEN ){
00381                 memcpy(decryptedBuf, buf, len);
00382                 bodyLength = len;
00383                 return;
00384         }
00385         
00386         if(passwordKey == NULL) {     
00387                 fprintf(stderr, "InPacket->decryptBody: password key not set yet, set decrypted length to 0\n");
00388                 bodyLength = 0;
00389                 return;
00390         }
00391         if((command != QQ_CMD_LOGIN) && (sessionKey == NULL)) {     
00392                 fprintf(stderr, "InPacket->decryptBody: session key not set yet, set decrypted length to 0\n");
00393                 command = -1;
00394                 bodyLength = 0;
00395                 return;
00396         } 
00397         if(command == QQ_CMD_LOGIN) {
00398                 ret = EvaCrypt::decrypt(buf, len, passwordKey, decryptedBuf, &bodyLength);
00399                 if(ret == 0){
00400                         bodyLength = MAX_PACKET_SIZE;
00401                         ret = EvaCrypt::decrypt(buf, len, iniKey, decryptedBuf, &bodyLength); 
00402                         if(ret == 0){
00403                                 printf("CANNOT DECRYPT! ----- login reply data(len:%d):\n", len);
00404                                 for(int i=0; i<len; i++){
00405                                         if(!(i%8)) printf("\n%d: ",i);
00406                                         char t = buf[i];
00407                                         printf("%2x ", (unsigned char)t);
00408                                 }
00409                                 printf("\n");
00410                         }
00411                 }
00412         } else {
00413                 ret = EvaCrypt::decrypt(buf, len, sessionKey, decryptedBuf, &bodyLength);
00414                 if(ret == 0){
00415                         bodyLength = MAX_PACKET_SIZE;
00416                         ret = EvaCrypt::decrypt(buf, len, passwordKey, decryptedBuf, &bodyLength);
00417                 }
00418         }
00419         if(ret == 0)
00420                 bodyLength = 0;
00421 }
00422 
00423 void InPacket::setInPacket( const InPacket * packet )
00424 {
00425         version = packet->getVersion();
00426         command = packet->getCommand();
00427         sequence = packet->getSequence();
00428         bodyLength = packet->getLength();
00429         if(!decryptedBuf){
00430                 delete decryptedBuf;
00431                 decryptedBuf = new unsigned char[bodyLength];
00432         }
00433         memcpy(decryptedBuf, packet->getBody(), bodyLength);        
00434 }
00435 
00436 const bool InPacket::parse( )
00437 {
00438         if(bodyLength){
00439                 parseBody();
00440                 return true;
00441         }else
00442                 return false;
00443 }
00444 

Generated on Mon May 15 20:48:41 2006 for libeva by  doxygen 1.4.4