diff options
author | sje <sje@4f64403b-2f21-0410-a795-97e2b3489a10> | 2007-06-28 08:34:59 +0000 |
---|---|---|
committer | sje <sje@4f64403b-2f21-0410-a795-97e2b3489a10> | 2007-06-28 08:34:59 +0000 |
commit | 6c417a45f25de9480ef200177c7bed0f4782eb19 (patch) | |
tree | f49a12a076e5fa20a95430998816a92fb741ebee | |
parent | 81a69c4c216350d48d962ac43fea3108498bbf33 (diff) |
git-svn-id: https://server.scottellis.com.au/svn/mim_plugs@219 4f64403b-2f21-0410-a795-97e2b3489a10
-rw-r--r-- | MySpace/MySpace.cpp | 6 | ||||
-rw-r--r-- | MySpace/MySpace.vcproj | 8 | ||||
-rw-r--r-- | MySpace/NetMessage.cpp | 21 | ||||
-rw-r--r-- | MySpace/NetMessage.h | 2 | ||||
-rw-r--r-- | MySpace/arc4.cpp | 52 | ||||
-rw-r--r-- | MySpace/arc4.h | 27 | ||||
-rw-r--r-- | MySpace/collection.h | 4 | ||||
-rw-r--r-- | MySpace/common.h | 3 | ||||
-rw-r--r-- | MySpace/proto.cpp | 2 | ||||
-rw-r--r-- | MySpace/server_con.cpp | 129 |
10 files changed, 224 insertions, 30 deletions
diff --git a/MySpace/MySpace.cpp b/MySpace/MySpace.cpp index 39540df..cb1da5d 100644 --- a/MySpace/MySpace.cpp +++ b/MySpace/MySpace.cpp @@ -6,6 +6,7 @@ #include "proto.h"
#include "net.h"
#include "menu.h"
+#include "arc4.h"
///////////////////////////////////////////////
// Common Plugin Stuff
@@ -13,6 +14,7 @@ HINSTANCE hInst;
PLUGINLINK *pluginLink;
HANDLE mainThread;
+int code_page;
PLUGININFOEX pluginInfo={
sizeof(PLUGININFOEX),
@@ -64,6 +66,9 @@ extern "C" __declspec (dllexport) int Load(PLUGINLINK *link) { pluginLink=link;
+ code_page = (int)CallService(MS_LANGPACK_GETCODEPAGE, 0, 0);
+
+ InitARC4Module();
InitOptions();
/////////////
@@ -82,6 +87,7 @@ extern "C" __declspec (dllexport) int Unload(void) { DeinitNetlib();
DeinitProto();
DeinitOptions();
+ DeinitARC4Module();
return 0;
}
diff --git a/MySpace/MySpace.vcproj b/MySpace/MySpace.vcproj index e0af73a..9e6d124 100644 --- a/MySpace/MySpace.vcproj +++ b/MySpace/MySpace.vcproj @@ -304,6 +304,10 @@ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
+ RelativePath=".\arc4.cpp"
+ >
+ </File>
+ <File
RelativePath=".\common.cpp"
>
<FileConfiguration
@@ -370,6 +374,10 @@ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
+ RelativePath=".\arc4.h"
+ >
+ </File>
+ <File
RelativePath=".\collection.h"
>
</File>
diff --git a/MySpace/NetMessage.cpp b/MySpace/NetMessage.cpp index 92ce21e..023a459 100644 --- a/MySpace/NetMessage.cpp +++ b/MySpace/NetMessage.cpp @@ -118,10 +118,10 @@ bool NetMessage::get_data(char *key, char *buff, int *size) { nbd.cbDecoded = *size;
//*size = Netlib_GetBase64DecodedBufferSize(nbd.cchEncoded);
- CallService(MS_NETLIB_BASE64DECODE, 0, (LPARAM)&nbd);
- *size = nbd.cbDecoded;
-
- return true;
+ if(CallService(MS_NETLIB_BASE64DECODE, 0, (LPARAM)&nbd)) {
+ *size = nbd.cbDecoded;
+ return true;
+ }
}
return false;
}
@@ -147,7 +147,7 @@ void ClientNetMessage::add_string(char *key, char *buff) { add(dat);
}
-void ClientNetMessage::add_data(char *key, char *data, int size) {
+bool ClientNetMessage::add_data(char *key, char *data, int size) {
int len = Netlib_GetBase64EncodedBufferSize(size);
char *buff = new char[len];
@@ -158,10 +158,15 @@ void ClientNetMessage::add_data(char *key, char *data, int size) { nbd.cbDecoded = size;
//*size = Netlib_GetBase64DecodedBufferSize(nbd.cchEncoded);
- CallService(MS_NETLIB_BASE64ENCODE, 0, (LPARAM)&nbd);
+ if(CallService(MS_NETLIB_BASE64ENCODE, 0, (LPARAM)&nbd)) {
+ KeyValue dat = KeyValue(NMString(key), NMString(buff));
+ add(dat);
+ delete[] buff;
+ return true;
+ }
- KeyValue dat = KeyValue(NMString(key), NMString(buff));
- add(dat);
+ delete[] buff;
+ return false;
}
void ClientNetMessage::add_int(char *key, int i) {
diff --git a/MySpace/NetMessage.h b/MySpace/NetMessage.h index 8261302..bae4ad7 100644 --- a/MySpace/NetMessage.h +++ b/MySpace/NetMessage.h @@ -49,7 +49,7 @@ public: int ClientNetMessage::make_packet(char *buff, int size);
void add_string(char *key, char *buff);
- void add_data(char *key, char *buff, int size);
+ bool add_data(char *key, char *buff, int size);
void add_int(char *key, int i);
static char *escape(char *val);
diff --git a/MySpace/arc4.cpp b/MySpace/arc4.cpp new file mode 100644 index 0000000..7060437 --- /dev/null +++ b/MySpace/arc4.cpp @@ -0,0 +1,52 @@ +#include "common.h"
+#include "arc4.h"
+
+void swap(char *b1, char *b2) {
+ char b = *b1;
+ *b1 = *b2;
+ *b2 = b;
+}
+
+void arc4_init(mir_arc4_ctx *ctx, char *key, int keylen) {
+ int i;
+ for(i = 0; i < 256; i++)
+ ctx->lookup[i] = i;
+
+ ctx->x = 0;
+ for(i = 0; i < 256; i++) {
+ ctx->x = (key[i % keylen] + ctx->lookup[i] + ctx->x) & 0xFF;
+ swap(&ctx->lookup[ctx->x], &ctx->lookup[i]);
+ }
+ ctx->x = 0;
+ ctx->y = 0;
+}
+
+void arc4_crypt(mir_arc4_ctx *ctx, char *dataIn, char *dataOut, int datalen) {
+ for(int i = 0; i < datalen; i++) {
+ ctx->x = (ctx->x + 1) & 0xFF;
+ ctx->y = (ctx->lookup[ctx->x] + ctx->y) & 0xFF;
+ swap(&ctx->lookup[ctx->x], &ctx->lookup[ctx->y]);
+ dataOut[i] = (dataIn[i] ^ ctx->lookup[(ctx->lookup[ctx->x] + ctx->lookup[ctx->y]) & 0xFF]);
+ }
+}
+
+int GetARC4Interface(WPARAM wParam, LPARAM lParam) {
+ struct ARC4_INTERFACE *arc4i = (struct ARC4_INTERFACE*) lParam;
+ if ( arc4i == NULL )
+ return 1;
+ if ( arc4i->cbSize != sizeof( struct ARC4_INTERFACE ))
+ return 1;
+
+ arc4i->arc4_init = arc4_init;
+ arc4i->arc4_crypt = arc4_crypt;
+ return 0;
+}
+
+HANDLE hService;
+void InitARC4Module() {
+ hService = CreateServiceFunction(MS_SYSTEM_GET_ARC4I, GetARC4Interface);
+}
+
+void DeinitARC4Module() {
+ DestroyServiceFunction(hService);
+}
diff --git a/MySpace/arc4.h b/MySpace/arc4.h new file mode 100644 index 0000000..ed453f0 --- /dev/null +++ b/MySpace/arc4.h @@ -0,0 +1,27 @@ +#ifndef _RC4_INC
+#define _RC4_INC
+
+typedef struct {
+ char lookup[256];
+ int x, y;
+} mir_arc4_ctx;
+
+struct ARC4_INTERFACE {
+ int cbSize;
+ void (*arc4_init)(mir_arc4_ctx *ctx, char *key, int keylen);
+ void (*arc4_crypt)(mir_arc4_ctx *ctx, char *dataIn, char *dataOut, int datalen);
+};
+
+#define MS_SYSTEM_GET_ARC4I "Miranda/System/GetARC4I"
+
+static __inline int mir_getARC4I( struct ARC4_INTERFACE* dest )
+{
+ dest->cbSize = sizeof(*dest);
+ return CallService( MS_SYSTEM_GET_ARC4I, 0, (LPARAM)dest );
+}
+
+
+void InitARC4Module();
+void DeinitARC4Module();
+
+#endif
diff --git a/MySpace/collection.h b/MySpace/collection.h index e02cedf..6daccfb 100644 --- a/MySpace/collection.h +++ b/MySpace/collection.h @@ -114,10 +114,6 @@ public: // queue/stack functions
// stack - use push/pop
// queue - use push_back/pop
- virtual void push(T &val) {
- add_front(val);
- }
-
virtual void push(T val) {
add_front(val);
}
diff --git a/MySpace/common.h b/MySpace/common.h index f80037c..1a7ae63 100644 --- a/MySpace/common.h +++ b/MySpace/common.h @@ -43,6 +43,8 @@ #include <winsock2.h> // for FD_SETSIZE
#include <m_netlib.h>
#include <m_clist.h>
+#include <m_utils.h>
+#include <m_langpack.h>
#include <m_popup.h>
@@ -63,5 +65,6 @@ extern HINSTANCE hInst;
extern PLUGINLINK *pluginLink;
extern HANDLE mainThread;
+extern int code_page;
#endif
diff --git a/MySpace/proto.cpp b/MySpace/proto.cpp index 4b3aa00..55b31c0 100644 --- a/MySpace/proto.cpp +++ b/MySpace/proto.cpp @@ -68,6 +68,8 @@ int GetInfo(WPARAM wParam,LPARAM lParam) { }
int SetStatus(WPARAM wParam,LPARAM lParam) {
+ if(wParam == status) return 0;
+
if(wParam != ID_STATUS_OFFLINE)
InitServerConnection();
else
diff --git a/MySpace/server_con.cpp b/MySpace/server_con.cpp index f3c6d79..79f20b8 100644 --- a/MySpace/server_con.cpp +++ b/MySpace/server_con.cpp @@ -1,14 +1,32 @@ #include "common.h"
#include "server_con.h"
#include "net.h"
+#include "arc4.h"
+#include "options.h"
#include "NetMessage.h"
#define SERVER_READ_BUFFER_SIZE (1024 * 32)
+/* TODO: obtain IPs of network interfaces from user's machine, instead of + * hardcoding these values below (used in msim_compute_login_response). + * This is not immediately + * important because you can still connect and perform basic + * functions of the protocol. There is also a high chance that the addreses + * are RFC1918 private, so the servers couldn't do anything with them + * anyways except make note of that fact. Probably important for any + * kind of direct connection, or file transfer functionality. + */ + +#define LOGIN_IP_LIST "\x00\x00\x00\x00\x05\x7f\x00\x00\x01\x00\x00\x00\x00\x0a\x00\x00\x40\xc0\xa8\x58\x01\xc0\xa8\x3c\x01" +#define LOGIN_IP_LIST_LEN 25 +
+#define NONCE_SIZE 0x20
+
int status = ID_STATUS_OFFLINE;
bool server_running = false, server_stop = false;
HANDLE server_connection = 0;
+int sesskey;
void CALLBACK sttMainThreadStatusCallback( ULONG dwParam ) {
if(status != dwParam) {
@@ -19,12 +37,75 @@ void CALLBACK sttMainThreadStatusCallback( ULONG dwParam ) { }
int waitcallback(unsigned int *timeout) {
- PUShowMessage("waitcallback", SM_NOTIFY);
+ //PUShowMessage("waitcallback", SM_NOTIFY);
return server_stop ? 0 : 1;
}
int try_ports[9] = {1863, 6660,6661,6662,6665,6668,6669,80,0443};
+void try_login(NetMessage &msg, HANDLE connection) {
+ char nonce[NONCE_SIZE * 2 + 2], *nc1 = nonce, *nc2 = nonce + NONCE_SIZE;
+ int size = NONCE_SIZE * 2 + 2;
+ if(msg.get_data("nc", nonce, &size) && size == NONCE_SIZE * 2) {
+ SHA1_INTERFACE sha1;
+ mir_sha1_ctx sha1_ctx;
+ mir_getSHA1I(&sha1);
+
+ ARC4_INTERFACE arc4;
+ mir_arc4_ctx arc4_ctx;
+ mir_getARC4I(&arc4);
+
+ char *ch_resp;
+ mir_sha1_byte_t pw_hash[20];
+ int ch_resp_size;
+ wchar_t wpw[256];
+ mir_sha1_byte_t key[20];
+ char email[256];
+
+#ifdef _UNICODE
+ _tcscpy(wpw, options.pw);
+ WideCharToMultiByte(CP_UTF8, 0, options.email, -1, email, 256, 0, 0);
+#else
+ strcpy(email, options.email);
+ MultiByteToWideChar(code_page, 0, options.pw, -1, wpw, 256);
+#endif
+
+ sha1.sha1_hash((mir_sha1_byte_t*)wpw, wcslen(wpw) * sizeof(wchar_t), pw_hash);
+
+ sha1.sha1_init(&sha1_ctx);
+ sha1.sha1_append(&sha1_ctx, (mir_sha1_byte_t*)pw_hash, 20);
+ sha1.sha1_append(&sha1_ctx, (mir_sha1_byte_t*)nc2, NONCE_SIZE);
+ sha1.sha1_finish(&sha1_ctx, key);
+
+ arc4.arc4_init(&arc4_ctx, (char *)key, 0x10);
+
+ ch_resp_size = NONCE_SIZE + strlen(email) + LOGIN_IP_LIST_LEN;
+ ch_resp = new char[ch_resp_size];
+ memcpy(ch_resp, nc1, NONCE_SIZE);
+ memcpy(ch_resp + NONCE_SIZE, email, strlen(email));
+ memcpy(ch_resp + NONCE_SIZE + strlen(email), LOGIN_IP_LIST, LOGIN_IP_LIST_LEN);
+
+ arc4.arc4_crypt(&arc4_ctx, ch_resp, ch_resp, ch_resp_size);
+
+ ClientNetMessage reply;
+ reply.add_int("login2", 196610);
+ reply.add_string("username", email);
+ reply.add_data("response", ch_resp, ch_resp_size);
+ reply.add_int("clientver", 673);
+ reply.add_int("reconn", 0);
+ reply.add_int("status", 100);
+ reply.add_int("id", 1);
+
+ delete[] ch_resp;
+
+ char packet[4096];
+ int packet_size = reply.make_packet(packet, 4096);
+ Netlib_Send(server_connection, packet, packet_size, MSG_DUMPASTEXT);
+ } else {
+ PUShowMessage("Nonce format error", SM_NOTIFY);
+ }
+}
+
void __cdecl ServerThreadFunc(void*) {
NETLIBOPENCONNECTION conn_data = {0};
conn_data.cbSize = sizeof(NETLIBOPENCONNECTION);
@@ -34,7 +115,8 @@ void __cdecl ServerThreadFunc(void*) { conn_data.timeout = 10;
conn_data.waitcallback = waitcallback;
- QueueUserAPC(sttMainThreadStatusCallback, mainThread, ID_STATUS_CONNECTING);
+ int conn_stat = ID_STATUS_CONNECTING;
+ QueueUserAPC(sttMainThreadStatusCallback, mainThread, conn_stat);
server_running = true;
@@ -44,12 +126,15 @@ void __cdecl ServerThreadFunc(void*) { int tries = 0;
bool login = true;
+ HANDLE connection = 0;
+
while(!Miranda_Terminated() && !server_stop) {
if(login) {
- if(server_connection) Netlib_CloseHandle(server_connection);
- server_connection = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hNetlibUser, (LPARAM)&conn_data);
+ if(connection) Netlib_CloseHandle(connection);
+ QueueUserAPC(sttMainThreadStatusCallback, mainThread, conn_stat++);
+ connection = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hNetlibUser, (LPARAM)&conn_data);
}
- bytes = Netlib_Recv(server_connection, (char *)recv_buffer, SERVER_READ_BUFFER_SIZE, MSG_DUMPASTEXT);
+ bytes = Netlib_Recv(connection, (char *)recv_buffer, SERVER_READ_BUFFER_SIZE, MSG_DUMPASTEXT);
if(bytes == 0) {
PUShowMessage("Connection closed", SM_NOTIFY);
@@ -59,32 +144,42 @@ void __cdecl ServerThreadFunc(void*) { break;
} else if(bytes == SOCKET_ERROR) {
PUShowMessage("Socket ERROR", SM_NOTIFY);
- break;
+ if(login && tries < 9) {
+ conn_data.wPort = try_ports[tries++];
+ } else
+ break;
} else {
if(login) {
+ QueueUserAPC(sttMainThreadStatusCallback, mainThread, conn_stat++);
login = false;
- QueueUserAPC(sttMainThreadStatusCallback, mainThread, ID_STATUS_ONLINE);
+ server_connection = connection;
+ DBWriteContactSettingDword(0, MODULE, "LastPort", conn_data.wPort);
}
- mir_snprintf(mt, 256, "recvd %d bytes", bytes);
- PUShowMessage(mt, SM_NOTIFY);
+ //mir_snprintf(mt, 256, "recvd %d bytes", bytes);
+ //PUShowMessage(mt, SM_NOTIFY);
NetMessage msg;
msg.parse(recv_buffer, bytes);
- if(msg.exists(NMString("lc"))) {
- NMString val;
- msg.get(NMString("lc"), val);
- mir_snprintf(mt, 256, "Login message: type is %s", val.text);
- PUShowMessage(mt, SM_NOTIFY);
- // challenge/response:
- //
+ if(msg.exists(NMString("error"))) {
+ char errmsg[256];
+ if(msg.get_string("errmsg", errmsg, 256))
+ PUShowMessage(errmsg, SM_WARNING);
+ } else if(msg.get_int("lc") == 1) {
+ QueueUserAPC(sttMainThreadStatusCallback, mainThread, conn_stat++);
+ try_login(msg, server_connection);
+ } else if(msg.get_int("lc") == 2) {
+ sesskey = msg.get_int("sesskey");
+ QueueUserAPC(sttMainThreadStatusCallback, mainThread, ID_STATUS_ONLINE);
} else if(msg.exists(NMString("persistr"))) {
+ /*
NMString cmd, dsn, lid;
msg.get(NMString("cmd"), cmd);
msg.get(NMString("dsn"), dsn);
msg.get(NMString("lid"), lid);
- mir_snprintf(mt, 256, "Perist message: type is %s,%s,%s", cmd.text, dsn.text, lid.text);
+ mir_snprintf(mt, 256, "Peristr message: type is %s,%s,%s", cmd.text, dsn.text, lid.text);
PUShowMessage(mt, SM_NOTIFY);
+ */
}
}
}
|