EXPORT int SkyLogin_PerformLoginOAuth(SkyLogin pPInst, const char *OAuth) { int ret; Skype_Inst *pInst = (Skype_Inst*)pPInst; if ((ret = PerformLogin(pInst, OAuth, NULL)) > 0) { // On successful login, save login datas Memory_U creds = Credentials_Write(pInst); if (creds.Memory) { SResponse LoginDatas; // We don't know user name, so read it from Credentials if (Credentials_Parse(creds, &LoginDatas) == 0) { uint Idx; for (Idx = 0; Idx < LoginDatas.NbObj; Idx++) { if (LoginDatas.Objs[Idx].Id == OBJ_ID_LDUSER) { Credentials_Save(creds, LoginDatas.Objs[Idx].Value.Memory.Memory); if (pInst->LoginD.User) free(pInst->LoginD.User); pInst->LoginD.User = strdup(LoginDatas.Objs[Idx].Value.Memory.Memory); break; } } FreeResponse(&LoginDatas); } free (creds.Memory); } } return ret; }
EXPORT int SkyLogin_LoadCredentials(SkyLogin pPInst, char *User) { Skype_Inst *pInst = (Skype_Inst*)pPInst; Memory_U creds = Credentials_Load(User); int ret = 0; if (creds.Memory) { // Credentials were found and loaded, now let's parse them. SResponse LoginDatas; if (Credentials_Read(pInst, creds, &LoginDatas) == 0) { // Credentials were successfully read :) // Now verify if they are still valid uint Idx; time_t t; for (Idx = 0, ret = 1; ret && Idx < LoginDatas.NbObj; Idx++) { switch (LoginDatas.Objs[Idx].Id) { case OBJ_ID_LDUSER: // Credentials for wrong user? ret = !strcasecmp(LoginDatas.Objs[Idx].Value.Memory.Memory, User); if (pInst->LoginD.User) free(pInst->LoginD.User); pInst->LoginD.User = strdup(LoginDatas.Objs[Idx].Value.Memory.Memory); break; case OBJ_ID_LDEXPIRY: // Credentials expired? ret = (int)LoginDatas.Objs[Idx].Value.Nbr * 60 > time(&t)-60; break; } } FreeResponse(&LoginDatas); } free(creds.Memory); } return ret; }
/* If Pass is NULL, User is assumed to be OAuth string and OAuth logon is performed */ static int SendAuthentificationBlobLS(Skype_Inst *pInst, LSConnection *pConn, const char *User, const char *Pass) { int64_t PlatForm; uchar AuthBlob[0xFFFF] = {0}; uchar SHAResult[32] = {0}; uchar Modulus[MODULUS_SZ * 2] = {0}; uchar ivec[AES_BLOCK_SIZE] = {0}; uchar ecount_buf[AES_BLOCK_SIZE] = {0}; uint MiscDatas[0x05] = {0}; uchar SessionKey[SK_SZ]; uchar *Browser; uchar *Mark; uchar *MarkObjL; uint Idx, Size, Crc, BSize, ret = 0; HttpsPacketHeader *HSHeader; uchar HSHeaderBuf[sizeof(HttpsPacketHeader)], RecvBuf[0x1000]; AES_KEY AesKey; MD5_CTX Context; RSA *SkypeRSA; ObjectDesc Obj2000, ObjSessionKey, ObjZBool1, ObjRequestCode, ObjZBool2, ObjModulus, ObjPlatForm, ObjLang, ObjMiscDatas, ObjVer, ObjPubAddr; SResponse Response={0}; if (!pInst->LoginD.RSAKeys) { BIGNUM *KeyExp; pInst->pfLog(pInst->pLogStream, "Generating RSA Keys Pair (Size = %d Bits)..\n", KEYSZ); pInst->LoginD.RSAKeys = RSA_new(); KeyExp = BN_new(); BN_set_word(KeyExp, RSA_F4); Idx = RSA_generate_key_ex(pInst->LoginD.RSAKeys, KEYSZ * 2, KeyExp, NULL); BN_free(KeyExp); if (Idx == -1) { pInst->pfLog(pInst->pLogStream, "Error generating Keys..\n\n"); RSA_free(pInst->LoginD.RSAKeys); pInst->LoginD.RSAKeys = NULL; return (0); } } Idx = BN_bn2bin(pInst->LoginD.RSAKeys->n, Modulus); Idx = BN_bn2bin(pInst->LoginD.RSAKeys->d, Modulus + Idx); Browser = AuthBlob; HSHeader = (HttpsPacketHeader *)Browser; memcpy(HSHeader->MAGIC, HTTPS_HSR_MAGIC, sizeof(HSHeader->MAGIC)); HSHeader->ResponseLen = htons(0xCD); Browser += sizeof(HttpsPacketHeader); *Browser++ = RAW_PARAMS; *Browser++ = 0x03; Obj2000.Family = OBJ_FAMILY_NBR; Obj2000.Id = OBJ_ID_2000; Obj2000.Value.Nbr = 0x2000; WriteObject(&Browser, Obj2000); SpecialSHA(pInst->SessionKey, SK_SZ, SHAResult, 32); AES_set_encrypt_key(SHAResult, 256, &AesKey); SkypeRSA = RSA_new(); BN_hex2bn(&(SkypeRSA->n), SkypeModulus1536[1]); BN_hex2bn(&(SkypeRSA->e), "010001"); Idx = RSA_public_encrypt(SK_SZ, pInst->SessionKey, SessionKey, SkypeRSA, RSA_NO_PADDING); RSA_free(SkypeRSA); if (Idx < 0) { pInst->pfLog(pInst->pLogStream, "RSA_public_encrypt failed..\n\n"); return (0); } ObjSessionKey.Family = OBJ_FAMILY_BLOB; ObjSessionKey.Id = OBJ_ID_SK; ObjSessionKey.Value.Memory.Memory = (uchar *)&SessionKey; ObjSessionKey.Value.Memory.MsZ = SK_SZ; WriteObject(&Browser, ObjSessionKey); ObjZBool1.Family = OBJ_FAMILY_NBR; ObjZBool1.Id = OBJ_ID_ZBOOL1; ObjZBool1.Value.Nbr = 0x01; WriteObject(&Browser, ObjZBool1); Mark = Browser; HSHeader = (HttpsPacketHeader *)Browser; memcpy(HSHeader->MAGIC, HTTPS_HSRR_MAGIC, sizeof(HSHeader->MAGIC)); HSHeader->ResponseLen = 0x00; Browser += sizeof(HttpsPacketHeader); MarkObjL = Browser; if (Pass) { ObjectDesc ObjUserName, ObjSharedSecret; *Browser++ = RAW_PARAMS; *Browser++ = 0x04; ObjRequestCode.Family = OBJ_FAMILY_NBR; ObjRequestCode.Id = OBJ_ID_REQCODE; ObjRequestCode.Value.Nbr = 0x1399; WriteObject(&Browser, ObjRequestCode); ObjZBool2.Family = OBJ_FAMILY_NBR; ObjZBool2.Id = OBJ_ID_ZBOOL2; ObjZBool2.Value.Nbr = 0x01; WriteObject(&Browser, ObjZBool2); ObjUserName.Family = OBJ_FAMILY_STRING; ObjUserName.Id = OBJ_ID_USERNAME; ObjUserName.Value.Memory.Memory = (uchar *)User; ObjUserName.Value.Memory.MsZ = (uchar)strlen(User); WriteObject(&Browser, ObjUserName); MD5_Init(&Context); MD5_Update(&Context, User, (ulong)strlen(User)); MD5_Update(&Context, CONCAT_SALT, (ulong)strlen(CONCAT_SALT)); MD5_Update(&Context, Pass, (ulong)strlen(Pass)); MD5_Final(pInst->LoginD.LoginHash, &Context); ObjSharedSecret.Family = OBJ_FAMILY_BLOB; ObjSharedSecret.Id = OBJ_ID_USERPASS; ObjSharedSecret.Value.Memory.Memory = (uchar *)pInst->LoginD.LoginHash; ObjSharedSecret.Value.Memory.MsZ = MD5_DIGEST_LENGTH; WriteObject(&Browser, ObjSharedSecret); *Browser++ = RAW_PARAMS; *Browser++ = 0x06; ObjModulus.Family = OBJ_FAMILY_BLOB; ObjModulus.Id = OBJ_ID_MODULUS; ObjModulus.Value.Memory.Memory = (uchar *)Modulus; ObjModulus.Value.Memory.MsZ = MODULUS_SZ; WriteObject(&Browser, ObjModulus); PlatForm = PlatFormSpecific(); ObjPlatForm.Family = OBJ_FAMILY_TABLE; ObjPlatForm.Id = OBJ_ID_PLATFORM; memcpy(ObjPlatForm.Value.Table, (uchar *)&PlatForm, sizeof(ObjPlatForm.Value.Table)); WriteObject(&Browser, ObjPlatForm); ObjLang.Family = OBJ_FAMILY_STRING; ObjLang.Id = OBJ_ID_LANG; ObjLang.Value.Memory.Memory = pInst->Language; ObjLang.Value.Memory.MsZ = sizeof(pInst->Language); WriteObject(&Browser, ObjLang); FillMiscDatas(pInst, MiscDatas); ObjMiscDatas.Family = OBJ_FAMILY_INTLIST; ObjMiscDatas.Id = OBJ_ID_MISCD; ObjMiscDatas.Value.Memory.Memory = (uchar *)MiscDatas; ObjMiscDatas.Value.Memory.MsZ = 0x05; WriteObject(&Browser, ObjMiscDatas); ObjVer.Family = OBJ_FAMILY_STRING; ObjVer.Id = OBJ_ID_VERSION; ObjVer.Value.Memory.Memory = (uchar *)VER_STR; ObjVer.Value.Memory.MsZ = (uchar)strlen(VER_STR); WriteObject(&Browser, ObjVer); ObjPubAddr.Family = OBJ_FAMILY_NBR; ObjPubAddr.Id = OBJ_ID_PUBADDR; ObjPubAddr.Value.Nbr = pInst->PublicIP; WriteObject(&Browser, ObjPubAddr); } else { int64_t PartnerId = 999; ObjectDesc ObjPartnerId, ObjOauth; // OAuth logon *Browser++ = RAW_PARAMS; *Browser++ = 0x02; ObjRequestCode.Family = OBJ_FAMILY_NBR; ObjRequestCode.Id = OBJ_ID_REQCODE; ObjRequestCode.Value.Nbr = 0x13a3; WriteObject(&Browser, ObjRequestCode); ObjZBool2.Family = OBJ_FAMILY_NBR; ObjZBool2.Id = OBJ_ID_ZBOOL2; ObjZBool2.Value.Nbr = 0x3d; WriteObject(&Browser, ObjZBool2); *Browser++ = RAW_PARAMS; *Browser++ = 0x08; ObjModulus.Family = OBJ_FAMILY_BLOB; ObjModulus.Id = OBJ_ID_MODULUS; ObjModulus.Value.Memory.Memory = (uchar *)Modulus; ObjModulus.Value.Memory.MsZ = MODULUS_SZ; WriteObject(&Browser, ObjModulus); PlatForm = PlatFormSpecific(); ObjPlatForm.Family = OBJ_FAMILY_TABLE; ObjPlatForm.Id = OBJ_ID_PLATFORM; memcpy(ObjPlatForm.Value.Table, (uchar *)&PlatForm, sizeof(ObjPlatForm.Value.Table)); WriteObject(&Browser, ObjPlatForm); FillMiscDatas(pInst, MiscDatas); ObjMiscDatas.Family = OBJ_FAMILY_INTLIST; ObjMiscDatas.Id = OBJ_ID_MISCD; ObjMiscDatas.Value.Memory.Memory = (uchar *)MiscDatas; ObjMiscDatas.Value.Memory.MsZ = 0x05; WriteObject(&Browser, ObjMiscDatas); ObjLang.Family = OBJ_FAMILY_STRING; ObjLang.Id = OBJ_ID_LANG; ObjLang.Value.Memory.Memory = pInst->Language; ObjLang.Value.Memory.MsZ = sizeof(pInst->Language); WriteObject(&Browser, ObjLang); ObjPartnerId.Family = OBJ_FAMILY_TABLE; ObjPlatForm.Id = OBJ_ID_PARTNERID; memcpy(ObjPlatForm.Value.Table, (uchar *)&PartnerId, sizeof(ObjPlatForm.Value.Table)); WriteObject(&Browser, ObjPlatForm); ObjOauth.Family = OBJ_FAMILY_STRING; ObjOauth.Id = OBJ_ID_OAUTH; ObjOauth.Value.Memory.Memory = (uchar *)User; ObjOauth.Value.Memory.MsZ = strlen(User); WriteObject(&Browser, ObjOauth); ObjVer.Family = OBJ_FAMILY_STRING; ObjVer.Id = OBJ_ID_VERSION; ObjVer.Value.Memory.Memory = (uchar *)VER_STR; ObjVer.Value.Memory.MsZ = (uchar)strlen(VER_STR); WriteObject(&Browser, ObjVer); ObjPubAddr.Family = OBJ_FAMILY_NBR; ObjPubAddr.Id = OBJ_ID_PUBADDR; ObjPubAddr.Value.Nbr = pInst->PublicIP; WriteObject(&Browser, ObjPubAddr); } Size = (uint)(Browser - MarkObjL); HSHeader->ResponseLen = htons((u_short)(Size + 0x02)); Idx = 0; memset(ivec, 0, AES_BLOCK_SIZE); memset(ecount_buf, 0, AES_BLOCK_SIZE); AES_ctr128_encrypt(MarkObjL, MarkObjL, Size, &AesKey, ivec, ecount_buf, &Idx); Crc = crc32(MarkObjL, Size, -1); *Browser++ = *((uchar *)(&Crc) + 0); *Browser++ = *((uchar *)(&Crc) + 1); Size = (uint)(Browser - AuthBlob); if (RC4Comm_Send(pConn, (const char *)AuthBlob, Size)<=0) { pInst->pfLog(pInst->pLogStream, "Sending to LS failed :'(..\n"); return (-1); } while (!ret && RC4Comm_Recv(pConn, (char *)&HSHeaderBuf, sizeof(HSHeaderBuf))>0) { HSHeader = (HttpsPacketHeader *)HSHeaderBuf; if (strncmp((const char *)HSHeader->MAGIC, HTTPS_HSRR_MAGIC, strlen(HTTPS_HSRR_MAGIC)) || RC4Comm_Recv(pConn, (char *)RecvBuf, (BSize=htons(HSHeader->ResponseLen)))<=0) { pInst->pfLog(pInst->pLogStream, "Bad Response..\n"); return (-2); } pInst->pfLog(pInst->pLogStream, "Auth Response Got..\n\n"); Idx = 0; memset(ivec, 0, AES_BLOCK_SIZE); memset(ecount_buf, 0, AES_BLOCK_SIZE); BSize-=2; ivec[3] = 0x01; ivec[7] = 0x01; AES_ctr128_encrypt(RecvBuf, RecvBuf, BSize, &AesKey, ivec, ecount_buf, &Idx); Browser = RecvBuf; while (Browser<RecvBuf+BSize) ManageObjects(&Browser, BSize, &Response); for (Idx = 0; Idx < Response.NbObj; Idx++) { uint LdIdx = 0; switch (Response.Objs[Idx].Id) { case OBJ_ID_LOGINANSWER: switch (Response.Objs[Idx].Value.Nbr) { case LOGIN_OK: pInst->pfLog(pInst->pLogStream, "Login Successful..\n"); ret = 1; break; default : pInst->pfLog(pInst->pLogStream, "Login Failed.. Bad Credentials..\n"); FreeResponse(&Response); return 0; } break; case OBJ_ID_CIPHERDLOGD: if (pInst->LoginD.SignedCredentials.Memory) free(pInst->LoginD.SignedCredentials.Memory); if (!(pInst->LoginD.SignedCredentials.Memory = malloc(Response.Objs[Idx].Value.Memory.MsZ))) { FreeResponse(&Response); return -2; } memcpy (pInst->LoginD.SignedCredentials.Memory, Response.Objs[Idx].Value.Memory.Memory, (pInst->LoginD.SignedCredentials.MsZ = Response.Objs[Idx].Value.Memory.MsZ)); break; } } FreeResponse(&Response); } return ret; }