status_t MSNConnection::HandleUSR( Command * command ) { LOG(kProtocolName, liDebug, "C %lX: Processing USR", this); status_t result = B_ERROR; if (strcmp(command->Param(0), "OK") == 0) { Progress("MSN Login", "MSN: Logged in!", 1.0); GoOnline(); BMessage statusChange(msnmsgOurStatusChanged); statusChange.AddInt8("status", fState); fManMsgr.SendMessage(&statusChange); /* * Depending on the server protocol, server location and the * account being used (non-hotmail/msn acc), the server will not * respond on the PRP MFN command and our connection will break. * Michael */ BString passport(fManager->Passport()); if ((B_ERROR != passport.FindFirst("@hotmail")) || (B_ERROR != passport.FindFirst("@msn"))) { LOG(kProtocolName, liDebug, "Sending PRP MSN command" ); Command *rea = new Command("PRP"); rea->AddParam("MFN"); rea->AddParam(fManager->DisplayName(), true); Send(rea); } else { LOG(kProtocolName, liDebug, "Not sending PRP MSN command!"); }; fManager->Handler()->ContactList(&fContacts); Command *adl = new Command("ADL"); std::list<BString> contacts; std::map<BString, std::list<BString> > domainUsers; fManager->Handler()->ContactList(&contacts); // Make our contact list into a list by domain for (std::list<BString>::iterator iIt = contacts.begin(); iIt != contacts.end(); iIt++) { BString user; BString domain; if (SplitEmail((*iIt).String(), user, domain) == B_OK) { std::map<BString, std::list<BString> >::iterator dIt = domainUsers.find(domain); if (dIt == domainUsers.end()) { std::list<BString> users; users.push_back(user); domainUsers[domain] = users; } else { dIt->second.push_back(user); }; }; }; BString payload = "<ml l=\"1\">"; // Package each contact by domain for (std::map<BString, std::list<BString> >::iterator dIt = domainUsers.begin(); dIt != domainUsers.end(); dIt++) { payload << "<d n=\"" << dIt->first << "\">"; for (std::list<BString>::iterator uIt = dIt->second.begin(); uIt != dIt->second.end(); uIt++) { payload << "<c n=\"" << (*uIt) << "\" l=\"3\" t=\"1\" />"; }; payload << "</d>"; }; payload << "</ml>"; adl->AddPayload(payload.String()); Send(adl); Command *chg = new Command("CHG"); chg->AddParam("NLN"); BString caps = ""; caps << kOurCaps; chg->AddParam( caps.String() ); Send(chg); result = B_OK; } else { BString URI = command->Param(2); BString nonce = command->Param(3); BString authResp = ""; BString authToken = ""; SSO *auth = new SSO(NULL, fManager->Passport(), fManager->Password(), URI.String(), nonce.String()); result = auth->Response(authToken, authResp); if (result == B_OK) { Command *reply = new Command("USR"); reply->AddParam("SSO"); reply->AddParam("S"); reply->AddParam(authToken.String()); reply->AddParam(authResp.String()); reply->Debug(); Send(reply); }; }; return result; }
status_t MSNConnection::HandleCHL( Command * command ) { LOG(kProtocolName, liDebug, "C %lX: Processing CHL", this); const char *challenge = command->Param(0); int i = 0; unsigned char buf[256]; char chlString[128]; long long high = 0; long long low = 0; long long temp = 0; long long key = 0; long long bskey = 0; int *chlStringArray = (int *)chlString; int *md5hash = (int *)buf; char hash1a[17]; char hash2a[17]; sprintf((char *)buf + 16, "%s%s", challenge, kClientCode); MD5(buf + 16, strlen((char *)buf + 16), buf); for (i = 0; i < 16; i++) { sprintf((char *)buf + 16 + i * 2,"%02x", buf[i]); }; for (i = 0; i < 4; i++) { md5hash[i] = md5hash[i] & 0x7FFFFFFF; }; i = (strlen(challenge) + strlen(kClientID) + 7) & 0xF8; sprintf(chlString,"%s%s00000000", challenge, kClientID); chlString[i] = 0; for (i = 0; i < (int)strlen(chlString) / 4; i += 2) { temp = chlStringArray[i]; temp = (0x0E79A9C1 * temp) % 0x7FFFFFFF; temp += high; temp = md5hash[0] * temp + md5hash[1]; temp = temp % 0x7FFFFFFF; high = chlStringArray[i + 1]; high = (high + temp) % 0x7FFFFFFF; high = md5hash[2] * high + md5hash[3]; high = high % 0x7FFFFFFF; low = low + high + temp; }; high = (high + md5hash[1]) % 0x7FFFFFFF; low = (low + md5hash[3]) % 0x7FFFFFFF; key = (low << 32) + high; for (i= 0; i < 8; i++) { bskey <<= 8; bskey += key & 255; key >>=8; }; strncpy((char *)hash1a, (char *)buf + 16, 16); strncpy((char *)hash2a, (char *)buf + 32, 16); hash1a[16] = '\0'; hash2a[16] = '\0'; sprintf((char *)buf, "%llx%llx", strtoull(hash1a,NULL,16) ^ bskey, strtoull(hash2a,NULL,16) ^ bskey); Command *reply = new Command("QRY"); reply->AddParam(kClientID); reply->AddPayload((char *)buf, 32); Send(reply); reply->Debug(); return B_OK; };