From dd2dab680b1112ecac3c2b77758b27bc2d72ef71 Mon Sep 17 00:00:00 2001 From: deuce <> Date: Wed, 13 Jan 2016 23:46:51 +0000 Subject: [PATCH] Add accept() and connect() methods to indicate the side you're on. Add name_ver argument to the constructor and corresponding property so that consumers of binkp.js can indicate their program name correctly. --- exec/load/binkp.js | 135 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 106 insertions(+), 29 deletions(-) diff --git a/exec/load/binkp.js b/exec/load/binkp.js index a9973e26ea..007ce86322 100644 --- a/exec/load/binkp.js +++ b/exec/load/binkp.js @@ -21,15 +21,12 @@ load("sockdefs.js"); * when a file is received successfully. * Intended for REQ/TIC processing. This callback can call * the addFile(filename) method (may not work unless - * ver1_1 is true) - * auth_callback - Function that is called with a list of addresses and a list of - * passwords (two arguments) which returns true if the session is secure - * or false if it is not. This callback cand also safely call - * addFile(filename) to add files for the authenticated addresses + * ver1_1 is true) + * name_ver - Name and version of program in "name/ver.ver.ver" format * * Now add any files you wish to send using the addFile(filename) method * - * Finally, call the session() method. + * Finally, call the connect() or accept() method * This method will return true if all files were transferred with no errors. * * After return, the sent_files and received_files arrays will contain @@ -38,14 +35,20 @@ load("sockdefs.js"); * transfer. */ -function BinkP(inbound, rx_callback, auth_callback) +function BinkP(name_ver, inbound, rx_callback) { var addr; + if (name_ver === undefined) + name_ver = 'JSBinkP/'+("$Revision$".split(' ')[1]); + this.name_ver = name_ver; + if (inbound === undefined) inbound = system.temp_dir; + this.inbound = backslash(inbound); + this.rx_callback = rx_callback; - this.auth_callback = auth_callback; + this.default_zone = 1; addr = this.parse_addr(system.fido_addr_list[0]); if (addr.zone !== undefined) @@ -61,7 +64,6 @@ function BinkP(inbound, rx_callback, auth_callback) this.sent_nr = false; this.ver1_1 = false; this.require_md5 = true; - this.inbound = backslash(inbound); this.timeout = 120; this.addr_list = []; this.system_name = system.name; @@ -168,7 +170,7 @@ BinkP.prototype.ack_file = function() this.receiving_len = undefined; this.receiving_date = undefined; } -} +}; BinkP.prototype.getCRAM = function(algo, key) { var tmp; @@ -199,16 +201,19 @@ BinkP.prototype.getCRAM = function(algo, key) tmp += '\x00'; tmp = md5_calc(str_xor(tmp, 0x5c) + binary_md5(str_xor(tmp, 0x36) + this.cram.challenge), true); return 'CRAM-'+algo+'-'+tmp; -} -BinkP.prototype.session = function(addr, password, port) +}; +BinkP.prototype.parseArgs = function(data) { + var ret = data.split(/ /); var i; + + for (i=0; i<ret.length; i++) + ret[i] = this.unescapeFileName(ret[i]); + return ret; +}; +BinkP.prototype.connect = function(addr, password, port) +{ var pkt; - var m; - var tmp; - var ver; - var args; - var size; if (addr === undefined) throw("No address specified!"); @@ -236,7 +241,7 @@ BinkP.prototype.session = function(addr, password, port) this.sendCmd(this.command.M_NUL, "LOC "+this.system_location); this.sendCmd(this.command.M_NUL, "NDL 115200,TCP,BINKP"); this.sendCmd(this.command.M_NUL, "TIME "+new Date().toString()); - this.sendCmd(this.command.M_NUL, "VER JSBinkP/0.0.0/"+system.platform+" binkp/1.1"); + this.sendCmd(this.command.M_NUL, "VER "+this.name_ver+system.platform+" binkp/1.1"); this.sendCmd(this.command.M_ADR, this.addr_list.join(' ')); while(!js.terminated && this.remote_addrs === undefined) { @@ -263,16 +268,88 @@ BinkP.prototype.session = function(addr, password, port) return false; } - function parse_args(that, data) - { - var ret = data.split(/ /); - var i; + if (js.terminated) { + this.close(); + return false; + } + return this.session(); +}; +/* + * sock can be either a lisening socket or a connected socket. + * + * auth_cb(addrs, passwds, challenge) is called to accept and add files + * if it returns true, the session is considered secure. auth_cb() + * is explicitly allowed to change the inbound property and call + * this.sendCmd(this.command.M_ERR, "Error String"); + * + * It is up to the auth_cb() callback to enforce the require_md5 property. + */ +BinkP.prototype.accept = function(sock, auth_cb) +{ + var challenge=''; + var i; - for (i=0; i<ret.length; i++) - ret[i] = that.unescapeFileName(ret[i]); - return ret; + if (sock === undefined || auth_cb === undefined) + return false; + + if (this.sock !== undefined) + this.close(); + + if (sock.is_connected) + this.sock = sock; + else + this.sock = sock.accept(); + + if (this.sock == undefined || !this.sock.is_connected) + return false; + + for (i=0; i<128; i++) + challenge += random(16).toString(16); + + this.authenticated = undefined; + this.sendCmd(this.command.M_NUL, "OPT CRAM-MD5-"+challenge); + this.sendCmd(this.command.M_NUL, "SYS "+this.system_name); + this.sendCmd(this.command.M_NUL, "ZYZ "+this.system_operator); + this.sendCmd(this.command.M_NUL, "LOC "+this.system_location); + this.sendCmd(this.command.M_NUL, "NDL 115200,TCP,BINKP"); + this.sendCmd(this.command.M_NUL, "TIME "+new Date().toString()); + this.sendCmd(this.command.M_NUL, "VER JSBinkP/0.0.0/"+system.platform+" binkp/1.1"); + this.sendCmd(this.command.M_ADR, this.addr_list.join(' ')); + + while(!js.terminated && this.authenticated === undefined) { + pkt = this.recvFrame(this.timeout); + if (pkt === undefined) + return false; + if (pkt !== null && pkt !== this.partialFrame) { + if (pkt.is_cmd) { + switch(pkt.command) { + case this.command.M_PWD: + if (auth_cb(this.remote_addrs, this.parseArgs(pkt.data), challenge)) + this.authenticated = 'secure'; + else + this.authenticated = 'non-secure'; + this.sendCmd(this.command.M_OK, this.authenticated) + } + } + } } + if (js.terminated) { + this.close(); + return false; + } + return this.session(); +}; +BinkP.prototype.session = function() +{ + var i; + var pkt; + var m; + var tmp; + var ver; + var args; + var size; + // Session set up, we're good to go! outer: while(!js.terminated && this.sock !== undefined) { @@ -288,7 +365,7 @@ BinkP.prototype.session = function(addr, password, port) break; case this.command.M_FILE: this.ack_file(); - args = parse_args(this, pkt.data); + args = this.parseArgs(pkt.data); if (args.length < 4) { log(LOG_ERROR, "Invalid M_FILE command args: '"+pkt.data+"'"); this.sendCmd(this.command.M_ERR, "Invalid M_FILE command args: '"+pkt.data+"'"); @@ -334,7 +411,7 @@ BinkP.prototype.session = function(addr, password, port) break outer; break; case this.command.M_GOT: - args = parse_args(this, pkt.data); + args = this.parseArgs(pkt.data); for (i=0; i<this.pending_ack.length; i++) { if (file_getname(this.pending_ack[i]) == args[0]) { this.sent_files.push(this.pending_ack[i]); @@ -344,7 +421,7 @@ BinkP.prototype.session = function(addr, password, port) } break; case this.command.M_GET: - args = parse_args(this, pkt.data); + args = this.parseArgs(pkt.data); // If we already sent this file, ignore the command... for (i=0; i<this.sent_files; i++) { if (file_getname(this.sent_files[i]) === args[0]) @@ -374,7 +451,7 @@ BinkP.prototype.session = function(addr, password, port) } break; case this.command.M_SKIP: - args = parse_args(this, pkt.data); + args = this.parseArgs(pkt.data); for (i=0; i<this.pending_ack.length; i++) { if (file_getname(this.pending_ack[i]) == args[0]) { this.pending_ack.splice(i, 1); -- GitLab