void ICQClient::snac_login(unsigned short type, unsigned short) { unsigned long newUin; switch (type){ case ICQ_SNACxLOGIN_ERROR: m_reconnect = NO_RECONNECT; m_socket->error_state(I18N_NOOP("Login error"), AuthError); break; case ICQ_SNACxLOGIN_REGISTER: if (data.owner.Uin.value){ m_socket->error_state(I18N_NOOP("Registered in no register state")); break; } m_socket->readBuffer.incReadPos(0x2E); m_socket->readBuffer.unpack(newUin); log(L_DEBUG, "Register %u %08lX", newUin, newUin); setUin(newUin); setState(Connecting); m_socket->connect(getServer(), getPort(), this); break; case ICQ_SNACxLOGIN_AUTHxKEYxRESPONSE: if (data.owner.Screen.ptr){ string md5_key; m_socket->readBuffer.unpackStr(md5_key); snac(ICQ_SNACxFAM_LOGIN, ICQ_SNACxLOGIN_MD5xLOGIN, false, false); m_socket->writeBuffer.tlv(0x0001, data.owner.Screen.ptr); MD5_CTX c; MD5_Init(&c); unsigned char md[MD5_DIGEST_LENGTH]; MD5_Update(&c, md5_key.c_str(), md5_key.length()); string pswd = getContacts()->fromUnicode(NULL, getPassword()); MD5_Update(&c, pswd.c_str(), pswd.length()); pswd = "AOL Instant Messenger (SM)"; MD5_Update(&c, pswd.c_str(), pswd.length()); MD5_Final(md, &c); m_socket->writeBuffer.tlv(0x0025, (char*)&md, sizeof(md)); m_socket->writeBuffer.tlv(0x0003, "AOL Instant Messenger, version 5.1.3036/WIN32"); m_socket->writeBuffer.tlv(0x0016, (unsigned short)0x0109); m_socket->writeBuffer.tlv(0x0017, (unsigned short)0x0005); m_socket->writeBuffer.tlv(0x0018, (unsigned short)0x0001); m_socket->writeBuffer.tlv(0x0019, (unsigned short)0x0000); m_socket->writeBuffer.tlv(0x001A, (unsigned short)0x0BDC); m_socket->writeBuffer.tlv(0x0014, 0x000000D2L); m_socket->writeBuffer.tlv(0x000F, "en"); m_socket->writeBuffer.tlv(0x000E, "us"); m_socket->writeBuffer.tlv(0x004A, "\x01"); sendPacket(); } break; case ICQ_SNACxLOGIN_LOGINxREPLY: chn_close(); break; default: log(L_WARN, "Unknown login family type %04X", type); } }
void ICQClient::snac_login(unsigned short type, unsigned short) { unsigned long newUin; switch (type){ case ICQ_SNACxLOGIN_ERROR: if (data.owner.Uin.value){ m_reconnect = NO_RECONNECT; m_socket->error_state(I18N_NOOP("Login error"), AuthError); break; } // in the process of registering; // it seems that we need to request bot protection picture; // reconnecting to send the request. log(L_DEBUG, "Verification required, reconnecting"); m_bVerifying = true; m_socket->close(); m_socket->connect(getServer(), getPort(), this); break; case ICQ_SNACxLOGIN_REGISTER: if (data.owner.Uin.value){ m_socket->error_state(I18N_NOOP("Registered in no register state")); break; } m_socket->readBuffer.incReadPos(0x2E); m_socket->readBuffer.unpack(newUin); log(L_DEBUG, "Register %lu %08lX", newUin, newUin); setUin(newUin); setState(Connecting); m_socket->connect(getServer(), getPort(), this); break; case ICQ_SNACxLOGIN_AUTHxKEYxRESPONSE: log(L_DEBUG, "Sending MD5 key"); if (data.owner.Screen.ptr || data.owner.Uin.value){ string md5_key; m_socket->readBuffer.unpackStr(md5_key); snac(ICQ_SNACxFAM_LOGIN, ICQ_SNACxLOGIN_MD5xLOGIN, false, false); if (data.owner.Uin.value){ char uin[20]; sprintf(uin, "%lu", data.owner.Uin.value); m_socket->writeBuffer.tlv(0x0001, uin); }else{ m_socket->writeBuffer.tlv(0x0001, data.owner.Screen.ptr); } string md = md5_key; md += getContacts()->fromUnicode(NULL, getPassword()); md += "AOL Instant Messenger (SM)"; md = md5(md.c_str()); m_socket->writeBuffer.tlv(0x0025, md.c_str(), md.length()); if (data.owner.Uin.value){ m_socket->writeBuffer.tlv(0x0003, "ICQ Inc. - Product of ICQ (TM).2003b.5.56.1.3916.85"); m_socket->writeBuffer.tlv(0x0016, 0x010A); m_socket->writeBuffer.tlv(0x0017, 0x0002); m_socket->writeBuffer.tlv(0x0018, 0x0038); m_socket->writeBuffer.tlv(0x0019, 0x0001); m_socket->writeBuffer.tlv(0x001A, 0x0F4C); m_socket->writeBuffer.tlv(0x0014, 0x00000055L); m_socket->writeBuffer.tlv(0x000f, "en"); m_socket->writeBuffer.tlv(0x000e, "us"); }else{ m_socket->writeBuffer.tlv(0x0003, "AOL Instant Messenger, version 5.1.3036/WIN32"); m_socket->writeBuffer.tlv(0x0016, (unsigned short)0x0109); m_socket->writeBuffer.tlv(0x0017, (unsigned short)0x0005); m_socket->writeBuffer.tlv(0x0018, (unsigned short)0x0001); m_socket->writeBuffer.tlv(0x0019, (unsigned short)0x0000); m_socket->writeBuffer.tlv(0x001A, (unsigned short)0x0BDC); m_socket->writeBuffer.tlv(0x0014, 0x000000D2L); m_socket->writeBuffer.tlv(0x000F, "en"); m_socket->writeBuffer.tlv(0x000E, "us"); m_socket->writeBuffer.tlv(0x004A, "\x01"); } sendPacket(true); } break; case ICQ_SNACxLOGIN_LOGINxREPLY: chn_close(); break; case ICQ_SNACxLOGIN_REGISTERxSEND_IMG: { m_bVerifying = false; TlvList tlv(m_socket->readBuffer); // currently there are 2 TLVs in SNAC(17,0D): // type = 1: the value contains the mime type of the image (image/jpeg); ignored // type = 2: the value contains the image itself in the binary form Tlv* tlvImage = tlv(2); if (!tlvImage) break; log(L_DEBUG, "Image length: %d bytes", tlvImage->Size()); uchar* buf = new uchar[tlvImage->Size()]; memcpy(buf, *tlvImage, tlvImage->Size()); QPixmap pict; if (!pict.loadFromData(buf, tlvImage->Size())) { delete[] buf; break; } delete[] buf; log(L_DEBUG, "Received verification image"); VerifyDlg verdlg(qApp->activeWindow(), pict); if (verdlg.exec() == QDialog::Accepted) // what to do if the user has cancelled the dialog? { QString verifyStr = verdlg.getVerifyString(); log(L_DEBUG, "User input: %s", verifyStr.latin1()); snac(ICQ_SNACxFAM_LOGIN, ICQ_SNACxLOGIN_REGISTERxREQ); Buffer msg; msg << 0x00000000L << 0x28000300L << 0x00000000L << 0x00000000L << 0x94680000L << 0x94680000L << 0x00000000L << 0x00000000L << 0x00000000L << 0x00000000L; string pswd = getContacts()->fromUnicode(NULL, getPassword()); unsigned short len = (unsigned short)(pswd.length() + 1); msg.pack(len); msg.pack(pswd.c_str(), len); msg << 0x94680000L << 0x00000602L; m_socket->writeBuffer.tlv(0x0001, msg); m_socket->writeBuffer.tlv(0x0009, verifyStr.latin1(), verifyStr.length()); sendPacket(true); } break; } default: log(L_WARN, "Unknown login family type %04X", type); } }
void ICQClient::packet_ready() { time(&m_lastTime); if (m_bHeader){ char c; readBuffer >> c; if (c != 0x2A){ log(L_ERROR, "Server send bad packet start code: %02X", c); error(ErrorProtocol); return; } readBuffer >> m_nChannel; unsigned short sequence, size; readBuffer >> sequence >> size; if (size){ readBuffer.add(size); m_bHeader = false; return; } } dumpPacket(readBuffer, 0,"Read"); switch (m_nChannel){ case ICQ_CHNxNEW: chn_login(); break; case ICQ_CHNxCLOSE: chn_close(); break; case ICQ_CHNxDATA:{ unsigned short fam, type; unsigned short flags, seq, cmd; readBuffer >> fam >> type >> flags >> seq >> cmd; switch (fam){ case ICQ_SNACxFAM_SERVICE: snac_service(type, seq); break; case ICQ_SNACxFAM_LOCATION: snac_location(type, seq); break; case ICQ_SNACxFAM_BUDDY: snac_buddy(type, seq); break; case ICQ_SNACxFAM_MESSAGE: snac_message(type, seq); break; case ICQ_SNACxFAM_BOS: snac_bos(type, seq); break; case ICQ_SNACxFAM_PING: snac_ping(type, seq); break; case ICQ_SNACxFAM_LISTS: snac_lists(type, seq); break; case ICQ_SNACxFAM_VARIOUS: snac_various(type, seq); break; case ICQ_SNACxFAM_LOGIN: snac_login(type, seq); break; default: log(L_WARN, "Unknown family %02X", fam); } break; } default: log(L_ERROR, "Unknown channel %u", m_nChannel & 0xFF); } processInfoRequestQueue(); processPhoneRequestQueue(0); processResponseRequestQueue(0); readBuffer.init(6); m_bHeader = true; }