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

evalogin.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 #include "evalogin.h"
00021 #ifdef _WIN32
00022 #include <winsock.h>
00023 #else
00024 #include <arpa/inet.h>
00025 #endif
00026 #include <string.h>
00027 #include <stdlib.h>
00028 #include "evacrypt.h"
00029 #include "evautil.h"
00030  
00031 LoginPacket::LoginPacket(unsigned char loginMode)
00032         : OutPacket(QQ_CMD_LOGIN, true),
00033         mLoginMode(loginMode)
00034 {
00035 }
00036 
00037 LoginPacket::LoginPacket(const LoginPacket &rhs)
00038         :OutPacket(rhs)
00039 {
00040         mLoginMode = rhs.getLoginMode();
00041 }
00042 
00043 LoginPacket::~LoginPacket()
00044 {
00045 }
00046 
00047 LoginPacket &LoginPacket::operator=(const LoginPacket &rhs)
00048 {
00049         *((OutPacket *)this) = (OutPacket)rhs;
00050         mLoginMode = rhs.getLoginMode();
00051         return *this;
00052 }
00053 
00054 int LoginPacket::putBody(unsigned char *buf) 
00055 {
00056         memcpy(buf, iniKey, QQ_KEY_LENGTH);
00057 
00058         int pos = 16;
00059         
00060         if(!getPasswordKey()){
00061                 fprintf(stderr, "LoginPacket->putBody: no password key avalible\n");
00062                 return 0;
00063         }
00064         
00065         unsigned char *login = new unsigned char[QQ_LOGIN_DATA_LENGTH];
00066         EvaCrypt::encrypt(NULL, 0, getPasswordKey(), login, &pos);
00067         
00068         memcpy(login+pos, login_16_51, 36);
00069         pos+=36;
00070         
00071         login[pos++] = mLoginMode;
00072         
00073         memcpy(login+pos, login_53_68, 16);
00074         pos+=16;
00075         
00076         login[pos++] = getLoginTokenLength();
00077         memcpy(login+pos, getLoginToken(), getLoginTokenLength());
00078         pos += getLoginTokenLength();
00079 
00080         memcpy(login+pos, login_94_193, 100);
00081         pos+= 100;
00082         
00083         memset(login+pos, 0, QQ_LOGIN_DATA_LENGTH - pos);
00084         
00085         unsigned char *encrypted = new unsigned char[MAX_PACKET_SIZE];
00086         int enLen=200;
00087         EvaCrypt::encrypt(login, QQ_LOGIN_DATA_LENGTH, iniKey, encrypted, &enLen);
00088         
00089         memcpy(buf+QQ_KEY_LENGTH, encrypted, enLen);
00090         
00091         delete login;
00092         delete encrypted;
00093         return QQ_KEY_LENGTH + enLen;
00094 }
00095 
00096 /* =========================================================== */
00097 
00098 LoginReplyPacket::LoginReplyPacket(unsigned char *buf, int len)
00099         : InPacket(buf, len)
00100 { 
00101 }   
00102 
00103 LoginReplyPacket::LoginReplyPacket(const LoginReplyPacket &rhs)
00104         : InPacket(rhs)
00105 {       
00106         replyCode = rhs.getReplyCode();
00107         redirectedIP = rhs.getRedirectedIP();
00108         redirectedPort = rhs.getRedirectedPort();
00109         
00110         qqNum = rhs.getQQ();
00111         IP = rhs.getMyIP();
00112         port = rhs.getMyPort();
00113         loginTime = rhs.getLoginTime();
00114         serverIP = rhs.getServerIP();
00115         serverPort = rhs.getServerPort();
00116         lastLoginIP = rhs.getLastLoginIP();
00117         lastLoginTime = rhs.getLastLoginTime();
00118         replyMessage = rhs.getReplyMessage();
00119 } 
00120 
00121 LoginReplyPacket &LoginReplyPacket::operator=(const LoginReplyPacket &rhs)
00122 {
00123         *((InPacket *)this) = (InPacket)rhs;
00124         replyCode = rhs.getReplyCode();
00125         redirectedIP = rhs.getRedirectedIP();
00126         redirectedPort = rhs.getRedirectedPort();
00127         
00128         qqNum = rhs.getQQ();
00129         IP = rhs.getMyIP();
00130         port = rhs.getMyPort();
00131         loginTime = rhs.getLoginTime();
00132         serverIP = rhs.getServerIP();
00133         serverPort = rhs.getServerPort();
00134         lastLoginIP = rhs.getLastLoginIP();
00135         lastLoginTime = rhs.getLastLoginTime();
00136         replyMessage = rhs.getReplyMessage();
00137         return *this;
00138 }
00139 
00140 void LoginReplyPacket::parseBody() 
00141 {
00142         replyCode = decryptedBuf[0];
00143         switch(replyCode) {     
00144         case QQ_LOGIN_REPLY_OK:
00145                 {
00146                         short tmp2;
00147                         unsigned int tmp4;
00148                         setSessionKey(decryptedBuf+1);
00149                         
00150                         // now we can set the file session key
00151                         char *fsbuf = new char[QQ_KEY_LENGTH + 4];
00152                         tmp4 = htonl(getQQ());
00153                         memcpy(fsbuf, &tmp4, 4);
00154                         memcpy(fsbuf+4, getSessionKey(), QQ_KEY_LENGTH);
00155                         setFileSessionKey((unsigned char *)EvaUtil::doMd5(fsbuf, 4 + QQ_KEY_LENGTH));
00156                         delete fsbuf;
00157                         
00158                         memcpy(&tmp4, decryptedBuf + QQ_KEY_LENGTH + 1, 4);
00159                         qqNum = ntohl(tmp4);
00160                         // 021-024  user IP
00161                         memcpy(&tmp4, decryptedBuf + 21, 4); 
00162                         IP = ntohl(tmp4);
00163                         // 025-026 user port
00164                         memcpy(&tmp2, decryptedBuf+25, 2);
00165                         port = ntohs(tmp2);
00166                         // 027-030 server IP
00167                         memcpy(&tmp4, decryptedBuf + 27, 4);
00168                         serverIP = ntohl(tmp4);
00169                         // 031-032 server port
00170                         memcpy(&tmp2, decryptedBuf+31, 2);
00171                         serverPort = ntohs(tmp2);
00172                         // 033-036  login time    
00173                         memcpy(&tmp4, decryptedBuf+33, 4);
00174                         loginTime = ntohl(tmp4);
00175                         
00176                         // 037-038 2 unknown bytes
00177                         
00178                         // 039-062 file share token used in Qun disk share file access
00179                         setFileShareToken(decryptedBuf+39);
00180                         
00181                         // 79-110  client key for QQ Home
00182                         setClientKey(decryptedBuf+79, 32); // always 32 bytes long
00183                         
00184                         // 123-126  user IP when last login
00185                         memcpy(&tmp4, decryptedBuf+123, 4);
00186                         lastLoginIP = ntohl(lastLoginIP);
00187                         // 127-130  last login time             
00188                         memcpy(&tmp4, decryptedBuf+127, 4);
00189                         lastLoginTime = ntohl(tmp4);
00190                         // 131-138 unknow bytes
00191                         break;
00192                 }
00193         case QQ_LOGIN_REPLY_PWD_ERROR:
00194                 // message from server when password is wrong. the messege is encoded by "GB18030"
00195                 {
00196                         char *tmpMsg = new char[bodyLength];
00197                         memcpy(tmpMsg, decryptedBuf+1, bodyLength-1);
00198                         tmpMsg[bodyLength-1]=0; 
00199                         replyMessage.assign(tmpMsg);
00200                         delete tmpMsg;
00201                         break;
00202                 }
00203         case QQ_LOGIN_REPLY_REDIRECT:
00204                 // redirect user to another server for balance reason
00205                 {
00206                         short tmp2;
00207                         int tmp4;
00208                         // 001-004 user qq number
00209                         memcpy(&tmp4, decryptedBuf + 1, 4);
00210                         qqNum = ntohl(tmp4);
00211                         // 005-008  the new server IP address
00212                         memcpy(&tmp4, decryptedBuf+5, 4);
00213                         redirectedIP = ntohl(tmp4);
00214                         // 009-010  the new server's Port number              
00215                         memcpy(&tmp2, decryptedBuf+9, 2);
00216                         redirectedPort = ntohs(tmp2);
00217                         break;
00218                 }
00219         default:
00220                 replyCode = QQ_LOGIN_REPLY_MISC_ERROR;
00221                 {
00222                         printf("login unknown reply(first byte is reply code)\n");
00223                         for(int i=0; i<bodyLength; i++){
00224                                 if(!(i%8)) printf("\n%d: ",i);
00225                                 char t = decryptedBuf[i];
00226                                 printf("%2x ", (uint8_t)t);
00227                         }
00228                         printf("\n");
00229                 }
00230                 break;
00231         }
00232 }
00233 
00234 /* =========================================================== */
00235 
00236 LogoutPacket::LogoutPacket()
00237         : OutPacket(QQ_CMD_LOGOUT, false)
00238 {
00239         sequence = 0xFFFF;
00240 }
00241 
00242 LogoutPacket::LogoutPacket(const LogoutPacket &rhs)
00243         : OutPacket(rhs)
00244 {
00245 }
00246 
00247 LogoutPacket &LogoutPacket::operator=(const LogoutPacket &rhs)
00248 {
00249         *((OutPacket *)this) = (OutPacket)rhs;
00250         return *this;
00251 }
00252 
00253 int LogoutPacket::putBody(unsigned char *buf) 
00254 {    
00255         unsigned char *pwKey = Packet::getPasswordKey();
00256         if(pwKey==NULL){
00257                 fprintf(stderr, "LogoutPacket->putBody: no password key avalible\n");
00258                 return 0;
00259         }
00260         memcpy(buf, pwKey, QQ_KEY_LENGTH);
00261         return QQ_KEY_LENGTH;
00262 }
00263 
00264 /* =========================================================== */
00265 
00266 KeepAlivePacket::KeepAlivePacket()
00267         : OutPacket(QQ_CMD_KEEP_ALIVE, true) 
00268 {
00269 }
00270 
00271 KeepAlivePacket::KeepAlivePacket(const KeepAlivePacket &rhs)
00272         : OutPacket(rhs) 
00273 {
00274 }
00275 
00276 KeepAlivePacket &KeepAlivePacket::operator=(const KeepAlivePacket &rhs )
00277 {
00278         *((OutPacket *)this) = (OutPacket)rhs;
00279         return *this;
00280 }
00281 
00282 int KeepAlivePacket::putBody(unsigned char *buf) 
00283 {
00284         int qq = htonl(getQQ());
00285         memcpy(buf, &qq, 4);
00286         return 4; 
00287 }
00288 
00289 /* =========================================================== */
00290 
00291 int KeepAliveReplyPacket::onlineUsers=0;
00292 
00293 KeepAliveReplyPacket::KeepAliveReplyPacket(unsigned char *buf, int len) 
00294         : InPacket(buf, len) 
00295 {
00296 }   
00297 
00298 KeepAliveReplyPacket::KeepAliveReplyPacket(const KeepAliveReplyPacket &rhs)
00299         : InPacket(rhs) 
00300 {
00301         onlineUsers = rhs.numOnlineUsers();
00302         myIP = rhs.getMyIP();
00303         myPort = rhs.getMyPort();
00304 }
00305 
00306 KeepAliveReplyPacket &KeepAliveReplyPacket::operator=(const KeepAliveReplyPacket &rhs)
00307 {
00308         *((InPacket *)this) = (InPacket)rhs;
00309         onlineUsers = rhs.numOnlineUsers();
00310         myIP = rhs.getMyIP();
00311         myPort = rhs.getMyPort();
00312         return *this;   
00313 }
00314  
00315 void KeepAliveReplyPacket::parseBody()
00316 {
00317         int sec = 0, offset = 0;
00318         char section[10][256];
00319         for(int i=0; i<bodyLength; i++){
00320                 if(sec>5) printf("Keep Alive -- number of fields greater than 5\n");
00321                 if(decryptedBuf[i]==KA_DIVIDER){
00322                         section[sec][offset] = 0;
00323                         sec++;
00324                         offset=0;
00325                         continue;
00326                 }
00327                 section[sec][offset++]=decryptedBuf[i]; 
00328         }
00329         section[sec][offset]=0;
00330         
00331         if(sec != 5){
00332                 printf("Keep Alive -- number of fields wrong!\n");
00333                 return;
00334         }
00335 
00336         onlineUsers = atoi(section[2]);
00337         if(onlineUsers == 0 ){
00338                 printf("KeepAliveReplyPacket -- parse online users error!\n");
00339                 return;
00340         }
00341        
00342         myIP.assign( section[3]);
00343         myPort = atoi(section[4]);
00344 }
00345 
00346 

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