Commit a032e47f authored by 神楽坂玲奈's avatar 神楽坂玲奈 Committed by Ma

mycard auth and ssl support

parent 7e28ce74
......@@ -9,12 +9,18 @@
"dialogues": "http://mercury233.me/ygosrv233/dialogues.json",
"redis_port": 6379,
"enable_random_duel": false,
"mycard_auth": "https://forum.touhou.cc",
"post_start_watching": true,
"TCG_banlist_id": 8,
"enable_TCG_as_default": false,
"http": {
"port": 7922,
"password": "123456"
"password": "123456",
"ssl": {
"port": 7923,
"cert": "/etc/ssl/ygopro-server.crt",
"key": "/etc/ssl/ygopro-server.key"
}
}
}
}
......@@ -15,7 +15,8 @@
"request": "latest",
"moment": "latest",
"sqlite3": "latest",
"bunyan": "latest"
"bunyan": "latest",
"ws": "latest"
},
"license": "AGPL-3.0",
"scripts": {
......
......@@ -5,6 +5,7 @@ url = require 'url'
path = require 'path'
fs = require 'fs'
os = require 'os'
crypto = require 'crypto'
execFile = require('child_process').execFile
#三方库
......@@ -317,6 +318,122 @@ ygopro.ctos_follow 'JOIN_GAME', false, (buffer, info, client, server)->
}
client.end()
else if info.pass.length and settings.modules.mycard_auth
ygopro.stoc_send_chat(client,'正在读取用户信息...', 11)
request
baseUrl: settings.modules.mycard_auth,
url: '/users/' + client.name + '.json'
qs:
api_key: '69675c315dfae3d7224688f2c56cf7d3f5016e7cf63f289d945709f11528b02e',
api_username: client.name,
skip_track_visit: true
json: true
, (error, response, body)->
if info.pass.length <= 8
ygopro.stoc_send_chat(client,'主机密码不正确 (Invalid Length)', 11)
ygopro.stoc_send client, 'ERROR_MSG',{
msg: 1
code: 2
}
client.end()
return
buffer = new Buffer(info.pass[0...8], 'base64')
check = (buf)->
checksum = 0
for i in [0...buf.length]
checksum += buf.readUInt8(i)
(checksum & 0xFF) == 0
if body and body.user
secret = body.user.id % 65535 + 1;
decrypted_buffer = new Buffer(6)
for i in [0,2,4]
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i)
if check(decrypted_buffer)
buffer = decrypted_buffer
# buffer != decrypted_buffer ==> auth failed
if !check(buffer)
ygopro.stoc_send_chat(client,'主机密码不正确 (Checksum Failed)', 11)
ygopro.stoc_send client, 'ERROR_MSG',{
msg: 1
code: 2
}
client.end()
return
action = buffer.readUInt8(1) >> 4
if buffer != decrypted_buffer and action in [1,2,4]
ygopro.stoc_send_chat(client,'主机密码不正确 (Unauthorized)', 11)
ygopro.stoc_send client, 'ERROR_MSG',{
msg: 1
code: 2
}
client.end()
return
# 1 create public room
# 2 create private room
# 3 join room
# 4 join match
switch action
when 1,2
name = crypto.createHash('md5').update(info.pass + client.name).digest('base64')[0...10].replace('+','-').replace('/', '_');
if Room.find_by_name(name)
ygopro.stoc_send_chat(client,'主机密码不正确 (Already Existed)', 11)
ygopro.stoc_send client, 'ERROR_MSG',{
msg: 1
code: 2
}
client.end()
return
opt1 = buffer.readUInt8(2)
opt2 = buffer.readUInt8(3)
opt3 = buffer.readUInt8(5)
options = {
lflist: 0
time_limit: 180
title: info.pass.slice(8)
private: action == 2
rule: (opt1 >> 5) & 3
mode: (opt1 >> 3) & 3
enable_priority: !!((opt1 >> 2) & 1)
no_check_deck: !!((opt1 >> 1) & 1)
no_shuffle_deck: !!(opt1 & 1)
start_lp: opt2
start_hand: opt3 >> 4
draw_count: opt3 & 0xF
}
room = new Room(name, options)
when 3
name = info.pass.slice(8)
room = Room.find_by_name(name)
if(!room)
ygopro.stoc_send_chat(client,'主机密码不正确 (Not Found)', 11)
ygopro.stoc_send client, 'ERROR_MSG',{
msg: 1
code: 2
}
client.end()
return
when 4
room = Room.find_or_create_by_name('M#' + info.pass.slice(8))
else
ygopro.stoc_send_chat(client,'主机密码不正确 (Invalid Action)', 11)
ygopro.stoc_send client, 'ERROR_MSG',{
msg: 1
code: 2
}
client.end()
return
client.room = room
client.room.connect(client)
else if info.pass.length && !Room.validate(info.pass)
#ygopro.stoc_send client, 'ERROR_MSG',{
# msg: 1
......@@ -679,7 +796,8 @@ setInterval ()->
#http
if settings.modules.http
http_server = http.createServer (request, response)->
requestListener = (request, response)->
parseQueryString = true
u = url.parse(request.url, parseQueryString)
pass_validated = u.query.pass == settings.modules.http.password
......@@ -741,4 +859,20 @@ if settings.modules.http
response.writeHead(404);
response.end();
return
http_server = http.createServer(requestListener)
http_server.listen settings.modules.http.port
if settings.modules.http.ssl
https = require 'https'
options =
cert: fs.readFileSync(settings.modules.http.ssl.cert)
key: fs.readFileSync(settings.modules.http.ssl.key)
https_server = https.createServer(options, requestListener)
WebSocketServer = require('ws').Server
websocket_server = new WebSocketServer
server: https_server
websocket_server.on 'connection', (connection) ->
console.log(room for room in Room.all when room.established)
https_server.listen settings.modules.http.ssl.port
\ No newline at end of file
// Generated by CoffeeScript 1.9.3
(function() {
var Graveyard, Room, _, bunyan, debug, dialogues, execFile, fs, http, http_server, log, moment, net, os, path, request, settings, tips, tribute, url, wait_room_start, ygopro;
var Graveyard, Room, WebSocketServer, _, bunyan, crypto, debug, dialogues, execFile, fs, http, http_server, https, https_server, log, moment, net, options, os, path, request, requestListener, settings, tips, tribute, url, wait_room_start, websocket_server, ygopro;
net = require('net');
......@@ -14,6 +14,8 @@
os = require('os');
crypto = require('crypto');
execFile = require('child_process').execFile;
_ = require('underscore');
......@@ -342,6 +344,128 @@
code: 2
});
client.end();
} else if (info.pass.length && settings.modules.mycard_auth) {
ygopro.stoc_send_chat(client, '正在读取用户信息...', 11);
request({
baseUrl: settings.modules.mycard_auth,
url: '/users/' + client.name + '.json',
qs: {
api_key: '69675c315dfae3d7224688f2c56cf7d3f5016e7cf63f289d945709f11528b02e',
api_username: client.name,
skip_track_visit: true
},
json: true
}, function(error, response, body) {
var action, check, decrypted_buffer, i, k, len, name, opt1, opt2, opt3, options, ref, room, secret;
if (info.pass.length <= 8) {
ygopro.stoc_send_chat(client, '主机密码不正确 (Invalid Length)', 11);
ygopro.stoc_send(client, 'ERROR_MSG', {
msg: 1,
code: 2
});
client.end();
return;
}
buffer = new Buffer(info.pass.slice(0, 8), 'base64');
check = function(buf) {
var checksum, i, k, ref;
checksum = 0;
for (i = k = 0, ref = buf.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) {
checksum += buf.readUInt8(i);
}
return (checksum & 0xFF) === 0;
};
if (body && body.user) {
secret = body.user.id % 65535 + 1;
decrypted_buffer = new Buffer(6);
ref = [0, 2, 4];
for (k = 0, len = ref.length; k < len; k++) {
i = ref[k];
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
}
if (check(decrypted_buffer)) {
buffer = decrypted_buffer;
}
}
if (!check(buffer)) {
ygopro.stoc_send_chat(client, '主机密码不正确 (Checksum Failed)', 11);
ygopro.stoc_send(client, 'ERROR_MSG', {
msg: 1,
code: 2
});
client.end();
return;
}
action = buffer.readUInt8(1) >> 4;
if (buffer !== decrypted_buffer && (action === 1 || action === 2 || action === 4)) {
ygopro.stoc_send_chat(client, '主机密码不正确 (Unauthorized)', 11);
ygopro.stoc_send(client, 'ERROR_MSG', {
msg: 1,
code: 2
});
client.end();
return;
}
switch (action) {
case 1:
case 2:
name = crypto.createHash('md5').update(info.pass + client.name).digest('base64').slice(0, 10).replace('+', '-').replace('/', '_');
if (Room.find_by_name(name)) {
ygopro.stoc_send_chat(client, '主机密码不正确 (Already Existed)', 11);
ygopro.stoc_send(client, 'ERROR_MSG', {
msg: 1,
code: 2
});
client.end();
return;
}
opt1 = buffer.readUInt8(2);
opt2 = buffer.readUInt8(3);
opt3 = buffer.readUInt8(5);
options = {
lflist: 0,
time_limit: 180,
title: info.pass.slice(8),
"private": action === 2,
rule: (opt1 >> 5) & 3,
mode: (opt1 >> 3) & 3,
enable_priority: !!((opt1 >> 2) & 1),
no_check_deck: !!((opt1 >> 1) & 1),
no_shuffle_deck: !!(opt1 & 1),
start_lp: opt2,
start_hand: opt3 >> 4,
draw_count: opt3 & 0xF
};
room = new Room(name, options);
break;
case 3:
name = info.pass.slice(8);
room = Room.find_by_name(name);
if (!room) {
ygopro.stoc_send_chat(client, '主机密码不正确 (Not Found)', 11);
ygopro.stoc_send(client, 'ERROR_MSG', {
msg: 1,
code: 2
});
client.end();
return;
}
break;
case 4:
room = Room.find_or_create_by_name('M#' + info.pass.slice(8));
break;
default:
ygopro.stoc_send_chat(client, '主机密码不正确 (Invalid Action)', 11);
ygopro.stoc_send(client, 'ERROR_MSG', {
msg: 1,
code: 2
});
client.end();
return;
}
client.room = room;
return client.room.connect(client);
});
} else if (info.pass.length && !Room.validate(info.pass)) {
ygopro.stoc_send_chat(client, "房间密码不正确", 11);
ygopro.stoc_send(client, 'ERROR_MSG', {
......@@ -814,7 +938,7 @@
}, 1000);
if (settings.modules.http) {
http_server = http.createServer(function(request, response) {
requestListener = function(request, response) {
var k, len, parseQueryString, pass_validated, player, ref, room, roomsjson, u;
parseQueryString = true;
u = url.parse(request.url, parseQueryString);
......@@ -900,8 +1024,37 @@
response.writeHead(404);
response.end();
}
});
};
http_server = http.createServer(requestListener);
http_server.listen(settings.modules.http.port);
if (settings.modules.http.ssl) {
https = require('https');
options = {
cert: fs.readFileSync(settings.modules.http.ssl.cert),
key: fs.readFileSync(settings.modules.http.ssl.key)
};
https_server = https.createServer(options, requestListener);
WebSocketServer = require('ws').Server;
websocket_server = new WebSocketServer({
server: https_server
});
websocket_server.on('connection', function(connection) {
var room;
return console.log((function() {
var k, len, ref, results;
ref = Room.all;
results = [];
for (k = 0, len = ref.length; k < len; k++) {
room = ref[k];
if (room.established) {
results.push(room);
}
}
return results;
})());
});
https_server.listen(settings.modules.http.ssl.port);
}
}
}).call(this);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment