mirror of
https://github.com/amigan/aim-oscar-server.git
synced 2025-01-31 13:02:44 -05:00
IT WORKS
This commit is contained in:
parent
19e26cddbb
commit
099ea1a69b
7 changed files with 140 additions and 17 deletions
|
@ -6,6 +6,7 @@ import BaseService from "./services/base";
|
||||||
|
|
||||||
export interface User {
|
export interface User {
|
||||||
uin: string,
|
uin: string,
|
||||||
|
username: string,
|
||||||
password: string,
|
password: string,
|
||||||
memberSince: Date,
|
memberSince: Date,
|
||||||
}
|
}
|
||||||
|
@ -97,8 +98,16 @@ export default class Communicator {
|
||||||
}
|
}
|
||||||
|
|
||||||
const tlv = TLV.fromBuffer(message.payload.slice(4));
|
const tlv = TLV.fromBuffer(message.payload.slice(4));
|
||||||
|
console.log('thing sent to channel 1:');
|
||||||
console.log(tlv.toString());
|
console.log(tlv.toString());
|
||||||
|
|
||||||
|
if (tlv.type === 0x06) {
|
||||||
|
// client sent us a cookie
|
||||||
|
const {cookie, user} = JSON.parse(tlv.payload.toString());
|
||||||
|
console.log('cookie:', cookie);
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
if (tlv.type === TLVType.GetServices) { // Requesting available services
|
if (tlv.type === TLVType.GetServices) { // Requesting available services
|
||||||
// this is just a dword list of subtype families
|
// this is just a dword list of subtype families
|
||||||
const servicesOffered : Buffer[] = [];
|
const servicesOffered : Buffer[] = [];
|
||||||
|
|
|
@ -47,9 +47,9 @@ const server = net.createServer((socket) => {
|
||||||
new PrivacyManagement(comm),
|
new PrivacyManagement(comm),
|
||||||
new UserLookup(comm),
|
new UserLookup(comm),
|
||||||
new UsageStats(comm),
|
new UsageStats(comm),
|
||||||
new ChatNavigation(comm),
|
// new ChatNavigation(comm),
|
||||||
new Chat(comm),
|
// new Chat(comm),
|
||||||
new DirectorySearch(comm),
|
// new DirectorySearch(comm),
|
||||||
new ServerStoredBuddyIcons(comm),
|
new ServerStoredBuddyIcons(comm),
|
||||||
new SSI(comm),
|
new SSI(comm),
|
||||||
];
|
];
|
||||||
|
|
|
@ -31,11 +31,21 @@ export default class GenericServiceControls extends BaseService {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.payload.subtype === 0x06) { // Client ask server for rate limits info
|
if (message.payload.subtype === 0x06) { // Client ask server for rate limits info
|
||||||
|
|
||||||
|
// HACK: set rate limits for all services. I can't tell which message subtypes they support so
|
||||||
|
// make it set rate limits for everything under 0x21.
|
||||||
|
const pairs : RateGroupPair[] = [];
|
||||||
|
Object.values(this.communicator.services).forEach((service) => {
|
||||||
|
for (let i = 0; i < 0x21; i++) {
|
||||||
|
pairs.push(new RateGroupPair(service.service, i));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const resp = new FLAP(0x02, this.nextReqID,
|
const resp = new FLAP(0x02, this.nextReqID,
|
||||||
SNAC.forRateClass(0x01, 0x07, [
|
SNAC.forRateClass(0x01, 0x07, [
|
||||||
new Rate(
|
new Rate(
|
||||||
new RateClass(1, 80, 2500, 2000, 1500, 800, 3400 /*fake*/, 6000, 0, 0),
|
new RateClass(1, 80, 2500, 2000, 1500, 800, 3400 /*fake*/, 6000, 0, 0),
|
||||||
new RatedServiceGroup(1, [new RateGroupPair(0x00, 0x00)])
|
new RatedServiceGroup(1, pairs),
|
||||||
)
|
)
|
||||||
]))
|
]))
|
||||||
this.send(resp);
|
this.send(resp);
|
||||||
|
@ -50,7 +60,7 @@ export default class GenericServiceControls extends BaseService {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.payload.subtype === 0x0e) { // Client requests own online information
|
if (message.payload.subtype === 0x0e) { // Client requests own online information
|
||||||
const uin = '400'; // this.communicator.user.uin;
|
const uin = this.communicator.user?.username || 'user';
|
||||||
const warning = 0;
|
const warning = 0;
|
||||||
const since = +(new Date('December 17, 1998 03:24:00'));
|
const since = +(new Date('December 17, 1998 03:24:00'));
|
||||||
const externalIP = dot2num(this.communicator.socket.remoteAddress!.split(':').pop()!);
|
const externalIP = dot2num(this.communicator.socket.remoteAddress!.split(':').pop()!);
|
||||||
|
|
|
@ -57,7 +57,6 @@ export default class ICBM extends BaseService {
|
||||||
const channel = payload.readUInt16BE(0);
|
const channel = payload.readUInt16BE(0);
|
||||||
|
|
||||||
// TODO: set settings based on channel provided
|
// TODO: set settings based on channel provided
|
||||||
|
|
||||||
this.channel = {
|
this.channel = {
|
||||||
channel,
|
channel,
|
||||||
messageFlags: payload.readUInt32BE(2),
|
messageFlags: payload.readUInt32BE(2),
|
||||||
|
@ -65,7 +64,7 @@ export default class ICBM extends BaseService {
|
||||||
maxSenderWarningLevel: payload.readUInt16BE(8),
|
maxSenderWarningLevel: payload.readUInt16BE(8),
|
||||||
maxReceiverWarningLevel: payload.readUInt16BE(10),
|
maxReceiverWarningLevel: payload.readUInt16BE(10),
|
||||||
minimumMessageInterval: payload.readUInt16BE(12),
|
minimumMessageInterval: payload.readUInt16BE(12),
|
||||||
unknown: payload.readUInt16BE(14),
|
unknown: 1000, //payload.readUInt16BE(14),
|
||||||
}
|
}
|
||||||
console.log("ICBM set channel", this.channel);
|
console.log("ICBM set channel", this.channel);
|
||||||
return;
|
return;
|
||||||
|
@ -81,10 +80,6 @@ export default class ICBM extends BaseService {
|
||||||
payload.writeInt16BE(this.channel.minimumMessageInterval, 12);
|
payload.writeInt16BE(this.channel.minimumMessageInterval, 12);
|
||||||
payload.writeInt16BE(this.channel.unknown, 14);
|
payload.writeInt16BE(this.channel.unknown, 14);
|
||||||
|
|
||||||
// For some reason this response crashes the client?
|
|
||||||
// It's identical to the channel set request the client
|
|
||||||
// sends earlier. Also the 3.x client sends a channel set request
|
|
||||||
// so early
|
|
||||||
const resp = new FLAP(0x02, this.nextReqID,
|
const resp = new FLAP(0x02, this.nextReqID,
|
||||||
new SNAC(0x04, 0x05, payload));
|
new SNAC(0x04, 0x05, payload));
|
||||||
this.send(resp);
|
this.send(resp);
|
||||||
|
|
|
@ -4,6 +4,6 @@ import Communicator from '../communicator';
|
||||||
// SSI is Server Stored Information
|
// SSI is Server Stored Information
|
||||||
export default class SSI extends BaseService {
|
export default class SSI extends BaseService {
|
||||||
constructor(communicator : Communicator) {
|
constructor(communicator : Communicator) {
|
||||||
super({service: 0x10, version: 0x01}, communicator)
|
super({service: 0x13, version: 0x01}, communicator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ const { AIM_MD5_STRING, FLAGS_EMPTY } = require('../consts');
|
||||||
const users : {[key: string]: User} = {
|
const users : {[key: string]: User} = {
|
||||||
'toof': {
|
'toof': {
|
||||||
uin: '156089',
|
uin: '156089',
|
||||||
|
username: 'toof',
|
||||||
password: 'foo',
|
password: 'foo',
|
||||||
memberSince: new Date('December 17, 1998 03:24:00'),
|
memberSince: new Date('December 17, 1998 03:24:00'),
|
||||||
}
|
}
|
||||||
|
@ -87,12 +88,18 @@ export default class AuthorizationRegistrationService extends BaseService {
|
||||||
new SNAC(0x17, 0x03, [
|
new SNAC(0x17, 0x03, [
|
||||||
TLV.forUsername(username), // username
|
TLV.forUsername(username), // username
|
||||||
TLV.forBOSAddress(chatHost), // BOS address
|
TLV.forBOSAddress(chatHost), // BOS address
|
||||||
TLV.forCookie(JSON.stringify({cookie: 'uwu', user: 'toof'})) // Authorization cookie
|
TLV.forCookie(JSON.stringify({cookie: 'uwu', user: users[username]})) // Authorization cookie
|
||||||
]));
|
]));
|
||||||
|
|
||||||
this.communicator.user = Object.assign({}, users[username], {username});
|
this.communicator.user = Object.assign({username}, users[username]);
|
||||||
|
console.log(this.communicator.user);
|
||||||
|
|
||||||
this.send(authResp);
|
this.send(authResp);
|
||||||
|
|
||||||
|
// tell them to leave
|
||||||
|
const disconnectResp = new FLAP(4, this.nextReqID, Buffer.alloc(0));
|
||||||
|
this.send(disconnectResp);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
case 0x06: // Request md5 authkey
|
case 0x06: // Request md5 authkey
|
||||||
const MD5AuthKeyHeader = Buffer.alloc(2, 0xFF, 'hex');
|
const MD5AuthKeyHeader = Buffer.alloc(2, 0xFF, 'hex');
|
||||||
|
|
108
src/util.ts
108
src/util.ts
|
@ -29,6 +29,7 @@ interface Spec {
|
||||||
isRepeat? : boolean,
|
isRepeat? : boolean,
|
||||||
isParam? : boolean,
|
isParam? : boolean,
|
||||||
isTLV? : boolean,
|
isTLV? : boolean,
|
||||||
|
dump? : boolean,
|
||||||
repeatSpecs?: Spec[],
|
repeatSpecs?: Spec[],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +57,10 @@ function tlv(description : string) : Spec {
|
||||||
return {size : -1, description, isTLV: true};
|
return {size : -1, description, isTLV: true};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dump() : Spec {
|
||||||
|
return {size: -1, description: '', dump: true};
|
||||||
|
}
|
||||||
|
|
||||||
function parseBuffer(buf : Buffer, spec : Spec[], repeatTimes = 0) {
|
function parseBuffer(buf : Buffer, spec : Spec[], repeatTimes = 0) {
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
let rows = [];
|
let rows = [];
|
||||||
|
@ -64,6 +69,12 @@ function parseBuffer(buf : Buffer, spec : Spec[], repeatTimes = 0) {
|
||||||
for (let section of spec) {
|
for (let section of spec) {
|
||||||
let value : any = 0;
|
let value : any = 0;
|
||||||
let bufStr : string = '';
|
let bufStr : string = '';
|
||||||
|
|
||||||
|
if (section.dump) {
|
||||||
|
rows.push({raw: logDataStream(buf.slice(offset))});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (section.size === 8) {
|
if (section.size === 8) {
|
||||||
bufStr = buf.slice(offset, offset + 1).toString('hex');
|
bufStr = buf.slice(offset, offset + 1).toString('hex');
|
||||||
value = buf.readInt8(offset);
|
value = buf.readInt8(offset);
|
||||||
|
@ -127,7 +138,15 @@ function parseBuffer(buf : Buffer, spec : Spec[], repeatTimes = 0) {
|
||||||
|
|
||||||
function printBuffer(buf : Buffer, spec : Spec[]) {
|
function printBuffer(buf : Buffer, spec : Spec[]) {
|
||||||
const rows = parseBuffer(buf, spec);
|
const rows = parseBuffer(buf, spec);
|
||||||
console.log((new Table(rows)).toString());
|
|
||||||
|
const lastRow = rows[rows.length - 1];
|
||||||
|
|
||||||
|
if (!!lastRow.raw) {
|
||||||
|
console.log((new Table(rows.slice(0, -1))).toString());
|
||||||
|
console.log(lastRow.raw);
|
||||||
|
} else {
|
||||||
|
console.log((new Table(rows)).toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function bufferFromWebText(webtext : string) : Buffer {
|
function bufferFromWebText(webtext : string) : Buffer {
|
||||||
|
@ -169,7 +188,7 @@ const SNAC_01_0F = [
|
||||||
dword("Last EXT status update time"),
|
dword("Last EXT status update time"),
|
||||||
];
|
];
|
||||||
|
|
||||||
const exampleWebText = ''+
|
const exSNAC_01_0F = ''+
|
||||||
`
|
`
|
||||||
2a 02 00 05 00 71 00 01
|
2a 02 00 05 00 71 00 01
|
||||||
00 0f 00 00 00 00 00 00
|
00 0f 00 00 00 00 00 00
|
||||||
|
@ -186,8 +205,91 @@ const exampleWebText = ''+
|
||||||
00 00 00 00 00 00 00 00
|
00 00 00 00 00 00 00 00
|
||||||
00 03 00 00 00 00 00 00
|
00 03 00 00 00 00 00 00
|
||||||
00 00 00 00 00 00 00
|
00 00 00 00 00 00 00
|
||||||
|
`;
|
||||||
|
|
||||||
|
const SNAC_01_07 = [
|
||||||
|
byte("FLAP Header"),
|
||||||
|
byte("Channel"),
|
||||||
|
word("Sequence ID"),
|
||||||
|
word("Payload Length"),
|
||||||
|
word("SNAC Family"),
|
||||||
|
word("SNAC Subtype"),
|
||||||
|
word("SNAC Flags"),
|
||||||
|
dword("SNAC Request-ID"),
|
||||||
|
|
||||||
|
repeat(16, "Number of Rate Classes", [
|
||||||
|
word('Rate class ID'),
|
||||||
|
dword('Window size'),
|
||||||
|
dword('Clear level'),
|
||||||
|
dword('Alert level'),
|
||||||
|
dword('Limit level'),
|
||||||
|
dword('Disconnect level'),
|
||||||
|
dword('Current level'),
|
||||||
|
dword('Max level'),
|
||||||
|
dword('Last time'),
|
||||||
|
byte('Current State'),
|
||||||
|
]),
|
||||||
|
|
||||||
|
dump(),
|
||||||
|
];
|
||||||
|
|
||||||
|
const exSNAC_01_07 = ''+
|
||||||
`
|
`
|
||||||
|
2a 02 00 05 03 3b 00 01 00 07 00 00 00 00
|
||||||
|
00 00 00 05 00 01 00 00 00 50 00 00 09 c4 00 00
|
||||||
|
07 d0 00 00 05 dc 00 00 03 20 00 00 16 dc 00 00
|
||||||
|
17 70 00 00 00 00 00 00 02 00 00 00 50 00 00 0b
|
||||||
|
b8 00 00 07 d0 00 00 05 dc 00 00 03 e8 00 00 17
|
||||||
|
70 00 00 17 70 00 00 00 7b 00 00 03 00 00 00 1e
|
||||||
|
00 00 0e 74 00 00 0f a0 00 00 05 dc 00 00 03 e8
|
||||||
|
00 00 17 70 00 00 17 70 00 00 00 00 00 00 04 00
|
||||||
|
00 00 14 00 00 15 7c 00 00 14 b4 00 00 10 68 00
|
||||||
|
00 0b b8 00 00 17 70 00 00 1f 40 00 00 00 7b 00
|
||||||
|
00 05 00 00 00 0a 00 00 15 7c 00 00 14 b4 00 00
|
||||||
|
10 68 00 00 0b b8 00 00 17 70 00 00 1f 40 00 00
|
||||||
|
00 7b 00 00 01 00 91 00 01 00 01 00 01 00 02 00
|
||||||
|
01 00 03 00 01 00 04 00 01 00 05 00 01 00 06 00
|
||||||
|
01 00 07 00 01 00 08 00 01 00 09 00 01 00 0a 00
|
||||||
|
01 00 0b 00 01 00 0c 00 01 00 0d 00 01 00 0e 00
|
||||||
|
01 00 0f 00 01 00 10 00 01 00 11 00 01 00 12 00
|
||||||
|
01 00 13 00 01 00 14 00 01 00 15 00 01 00 16 00
|
||||||
|
01 00 17 00 01 00 18 00 01 00 19 00 01 00 1a 00
|
||||||
|
01 00 1b 00 01 00 1c 00 01 00 1d 00 01 00 1e 00
|
||||||
|
01 00 1f 00 01 00 20 00 01 00 21 00 02 00 01 00
|
||||||
|
02 00 02 00 02 00 03 00 02 00 04 00 02 00 06 00
|
||||||
|
02 00 07 00 02 00 08 00 02 00 0a 00 02 00 0c 00
|
||||||
|
02 00 0d 00 02 00 0e 00 02 00 0f 00 02 00 10 00
|
||||||
|
02 00 11 00 02 00 12 00 02 00 13 00 02 00 14 00
|
||||||
|
02 00 15 00 03 00 01 00 03 00 02 00 03 00 03 00
|
||||||
|
03 00 06 00 03 00 07 00 03 00 08 00 03 00 09 00
|
||||||
|
03 00 0a 00 03 00 0b 00 03 00 0c 00 04 00 01 00
|
||||||
|
04 00 02 00 04 00 03 00 04 00 04 00 04 00 05 00
|
||||||
|
04 00 07 00 04 00 08 00 04 00 09 00 04 00 0a 00
|
||||||
|
04 00 0b 00 04 00 0c 00 04 00 0d 00 04 00 0e 00
|
||||||
|
04 00 0f 00 04 00 10 00 04 00 11 00 04 00 12 00
|
||||||
|
04 00 13 00 04 00 14 00 06 00 01 00 06 00 02 00
|
||||||
|
06 00 03 00 08 00 01 00 08 00 02 00 09 00 01 00
|
||||||
|
09 00 02 00 09 00 03 00 09 00 04 00 09 00 09 00
|
||||||
|
09 00 0a 00 09 00 0b 00 0a 00 01 00 0a 00 02 00
|
||||||
|
0a 00 03 00 0b 00 01 00 0b 00 02 00 0b 00 03 00
|
||||||
|
0b 00 04 00 0c 00 01 00 0c 00 02 00 0c 00 03 00
|
||||||
|
13 00 01 00 13 00 02 00 13 00 03 00 13 00 04 00
|
||||||
|
13 00 05 00 13 00 06 00 13 00 07 00 13 00 08 00
|
||||||
|
13 00 09 00 13 00 0a 00 13 00 0b 00 13 00 0c 00
|
||||||
|
13 00 0d 00 13 00 0e 00 13 00 0f 00 13 00 10 00
|
||||||
|
13 00 11 00 13 00 12 00 13 00 13 00 13 00 14 00
|
||||||
|
13 00 15 00 13 00 16 00 13 00 17 00 13 00 18 00
|
||||||
|
13 00 19 00 13 00 1a 00 13 00 1b 00 13 00 1c 00
|
||||||
|
13 00 1d 00 13 00 1e 00 13 00 1f 00 13 00 20 00
|
||||||
|
13 00 21 00 13 00 22 00 13 00 23 00 13 00 24 00
|
||||||
|
13 00 25 00 13 00 26 00 13 00 27 00 13 00 28 00
|
||||||
|
15 00 01 00 15 00 02 00 15 00 03 00 02 00 06 00
|
||||||
|
03 00 04 00 03 00 05 00 09 00 05 00 09 00 06 00
|
||||||
|
09 00 07 00 09 00 08 00 03 00 02 00 02 00 05 00
|
||||||
|
04 00 06 00 04 00 02 00 02 00 09 00 02 00 0b 00
|
||||||
|
05 00 00
|
||||||
|
`;
|
||||||
|
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
printBuffer(bufferFromWebText(exampleWebText), SNAC_01_0F);
|
printBuffer(bufferFromWebText(exSNAC_01_07), SNAC_01_07);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue