parent $root
object $backdoor
var $root dbref 'backdoor
var $root child_index 27
var $root fertile 0
var $root manager $backdoor
var $root owned [$backdoor, $]
var $root owners [$]
var $root writable []
var $root readable []
var $root inited 1
var $backdoor buffer `[]
var $backdoor ip ""
var $backdoor hostname ""
var $backdoor line_buffer []
var $backdoor valid_hosts [""]
var $backdoor passwords #[["back1", "*"], ["back2", "*"]]
var $backdoor connected 1
var $backdoor programming 0
var $backdoor port 1169
var $backdoor who ""
method init_backdoor
if (caller() != $root)
throw(~perm, "Caller is not $root.");
buffer = `[];
ip = "";
hostname = "";
line_buffer = [];
programming = #[];
who = "";
.
method uninit_backdoor
if (caller() != $root)
throw(~perm, "Caller is not $root.");
buffer = `[];
ip = "";
hostname = "";
line_buffer = [];
programming = [];
.
method parse
arg incoming;
var lines, line, index;
// called by the server with an incoming buffer
if (sender() || caller())
throw(~perm, "Sender and caller are not the server");
lines = buffer_to_strings(buffer_append(buffer, incoming));
index = listlen(lines);
buffer = lines[index];
lines = delete(lines, index);
line_buffer = [@line_buffer, @lines];
while (line_buffer) {
line = line_buffer[1];
line_buffer = delete(line_buffer, 1);
(| .parse_line(line) |);
}
.
method parse_line
arg line;
var l;
if (sender() != this())
throw(~perm, "Sender is not this.");
catch any {
if (connected) {
if (programming)
._handle_programming_line(line);
else
._handle_command_line(line);
} else {
._handle_login(line);
}
} with handler {
for l in ($parse.traceback(traceback()))
.echo(l);
}
.
method quit_cmd
arg [cmd];
if (sender() != this())
throw(~perm, "Sender is not this.");
.echo("Goodbye.");
.backdoor_log(("Disconnect <" + (.address())) + ">");
.close();
.
method eval_cmd
arg cmd, [args];
var code, result;
if (sender() != this())
throw(~perm, "Sender is not this.");
code = (args.to_string()) + ";";
result = .eval([code], this());
if ((result[1]) == 'errors)
.echo(result[2]);
else
.echo("=> " + toliteral(result[2]));
.
method eval_as_cmd
arg cmd, [args];
var result, code, obj;
if (sender() != this())
throw(~perm, "Sender is not this.");
args = args.to_string();
result = match_template("* eval *", args);
if (!result) {
.echo("Syntax: `as <object> eval <code>`");
return;
}
obj = (| $object.to_dbref(result[1]) |);
if (!obj) {
.echo(("Unable to find object \"" + (result[1])) + "\".");
return;
}
code = (result[3]) + ";";
result = obj.eval([code]);
if ((result[1]) == 'errors)
.echo(result[2]);
else
.echo("as eval => " + toliteral(result[2]));
.
method echo
arg what;
var line;
if (type(what) == 'list) {
for line in (what)
.echo(line);
} else {
._echo(what);
}
.
method eval_as_to_cmd
arg cmd, [args];
var result, code, obj, target;
if (sender() != this())
throw(~perm, "Sender is not this.");
args = args.to_string();
result = match_template("* as * eval *", args);
if (!result) {
.echo("Syntax: `definer <object> as <object> eval <code>`");
return;
}
obj = (| $object.to_dbref(result[1]) |);
target = (| $object.to_dbref(result[3]) |);
if (!obj) {
.echo(("Unable to find object \"" + (result[1])) + "\".");
return;
}
if (!target) {
.echo(("Unable to find object \"" + (result[3])) + "\".");
return;
}
code = (result[5]) + ";";
result = obj.eval([code], target);
if ((result[1]) == 'errors)
.echo(result[2]);
else
.echo("definer as eval => " + toliteral(result[2]));
.
method close
if (sender() != this())
throw(~perm, "Sender is not this.");
close_connection();
if (sender() != definer())
.destroy();
.
method set_password
arg what, word;
var x, i, a, cword;
if (!($sys.is_admin(sender()))) {
.log_backdoor("Invalid set password attempt by " + (sender().namef('xref)));
throw(~perm, "Permission denied, only admins may set backdoor passwords.");
}
if (strlen(word) < 6)
throw(~badpasswd, "Passwords must be at least 6 characters long.");
for x in [1 .. strlen(word)] {
if ((word[x]) in "1234567890")
i = i + 1;
else
a = a + 1;
}
if ((a < 2) || (i < 2))
throw(~badpasswd, "Passwords must contain at least 2 numeric characters and 2 non-numeric characters.");
cword = crypt(word);
if (cword in (passwords.values()))
throw(~badpasswd, "That password already exists.");
passwords = dict_add(passwords, what, cword);
.
method del_password
arg what;
if (!($sys.is_admin(sender()))) {
.log_backdoor("Invalid password removal attempt by " + (sender().namef('xref)));
throw(~perm, "Permission denied, only admins may adjust backdoor passwords.");
}
passwords = dict_del(passwords, what);
.
method address
arg [args];
if (sender() != this())
throw(~perm, "Sender is not this.");
args = [@args, 'hostname][1];
switch (args) {
case 'ip:
return ip;
case 'hostname:
return hostname;
}
.
method set_address
arg host;
if ((sender() != this()) && (!(sender().has_ancestor(definer()))))
throw(~perm, "Sender is not this.");
ip = host;
hostname = hostname(ip);
.
method connect
arg host, socket;
var c;
if (sender() || caller())
throw(~perm, "Sender is not the server.");
if (!(host in valid_hosts)) {
.backdoor_log("Connection from invalid host: " + host);
.echo("Your host is not one of the valid hosts.");
.close();
return;
}
.backdoor_log("Connection from: " + host);
c = .spawn();
if ($sys.reassign_connection(c))
c.set_address(host);
else
c.destroy();
.
method program
if (sender() != this())
throw(~perm, "Sender is not this.");
programming = #[['task_id, task_id()], ['code, []]];
return $sys.suspend();
.
method check_passwords
arg str;
var line, pwd;
if (sender() != this())
throw(~perm, "Sender is not this.");
line = explode(str);
pwd = $backdoor.passwords();
if ((!(| pwd[line[1]] |)) || ((listlen(line) != 4) || ((!(.check_encrypted(line[1], line[2]))) || ((!(.check_encrypted("back1", line[3]))) || (!(.check_encrypted("back2", line[4])))))))
return 0;
return 1;
.
method disconnect
arg [args];
if (sender() || caller())
throw(~perm, "Sender is not the server.");
.close();
.
method startup
arg [args];
var opt, curr_port;
(> .perms(caller(), $sys) <);
catch any {
opt = "-pbackdoor" in args;
curr_port = (| toint(args[opt + 1]) |) || port;
$sys.log(("** Starting $backdoor on port " + tostr(curr_port)) + " **");
$sys.bind_port(curr_port, this());
} with handler {
$sys.log($parse.traceback(traceback()));
}
.
method passwords
if (!(sender().has_ancestor(this())))
throw(~perm, "Sender is not descended from this.");
return passwords;
.
method backdoor_log
arg str;
if (sender() != this())
throw(~perm, "Sender is not this.");
$sys.log(((((.dbref()) + " (") + who) + "): ") + str);
.
method check_encrypted
arg key, str;
var pwd;
pwd = ($backdoor.passwords())[key];
if (sender() != this())
throw(~perm, "Sender is not this.");
return crypt(str, substr(pwd, 1, 2)) == pwd;
.
method _echo
arg what;
// send off a string or buffer
if (sender() != this())
throw(~perm, "Sender is not this.");
(> echo(buffer_from_strings([what])) <);
.
method program_cmd
arg cmd, what;
var code, ref, ignore, errors;
if (sender() != this())
throw(~perm, "Sender is not this.");
ref = $parse.full_reference(what);
if (((ref[1]) != 'method) || (!(ref[3]))) {
.echo("Invalid object.method() reference, ignoring code until \".\"");
ignore = 1;
}
.echo(((("-- Enter text for " + ((ref[2]).dbref())) + ".") + tostr(ref[3])) + " --");
code = .program();
if (code == 'aborted) {
.echo("** Aborted **");
} else if (ignore) {
.echo("Finished ignoring text.");
} else {
errors = (ref[2]).compile(code, ref[3]);
if (errors)
.echo(errors);
else
.echo("Method compiled.");
}
.
method _handle_programming_line
arg line;
if (sender() != this())
throw(~perm, "Sender is not this.");
if (!line) {
programming = programming.add_elem('code, "");
} else if (line == ".") {
$sys.resume(programming['task_id], programming['code]);
programming = #[];
} else if (line == "@abort") {
$sys.cancel(programming['task_id]);
programming = #[];
.echo("** Aborted **");
} else {
programming = programming.add_elem('code, line);
}
.
method _handle_command_line
arg line;
var cmds, cmd;
if (sender() != this())
throw(~perm, "Sender is not this.");
//
cmds = "list, program, quit, eval, as eval, def as eval";
if (!line) {
.echo("Available commands: " + cmds);
return;
}
// because I'm lazy, check for ';'
if ((line[1]) == ";")
line = "eval " + substr(line, 2);
.backdoor_log("Command: " + line);
cmd = explode(line);
switch (cmd[1]) {
case "@program", ".program", "program":
.program_cmd(@cmd);
case "@quit", "quit":
.quit_cmd(@cmd);
case "eval":
.eval_cmd(@cmd);
case "as":
.eval_as_cmd(@cmd);
case "definer", "def":
.eval_as_to_cmd(@cmd);
case "list", "@list", "@nlist":
.list_cmd(@cmd);
default:
.echo("Available commands: " + cmds);
}
.
method _handle_login
arg line;
if (sender() != this())
throw(~perm, "Sender is not the definer.");
if (.check_passwords(line)) {
connected = 1;
who = (line.explode())[1];
.backdoor_log("Valid login sequence.");
.echo("Valid login sequence.");
} else {
.backdoor_log((("Invalid login sequence (" + ((| line[1] |) || "<none>")) + " ...) from: ") + (.address()));
.echo("Invalid login sequence.");
.close();
}
.
method list_cmd
arg cmd, what;
var code, ref, ancestor, nums, line;
if (sender() != this())
throw(~perm, "Sender is not this.");
ref = $parse.full_reference(what);
nums = cmd == "@nlist";
if (((ref[1]) != 'method) || (!(ref[3]))) {
.echo("Invalid object.method() reference.");
return;
}
ancestor = (ref[2]).find_method(ref[3]);
code = ancestor.list_method(ref[3]);
if (nums) {
for line in [1 .. listlen(code)]
code = replace(code, line, ((((line < 10) ? " " | "") + tostr(line)) + ": ") + (code[line]));
} else {
for line in [1 .. listlen(code)]
code = replace(code, line, " " + (code[line]));
}
.echo((("program " + ((ref[2]).dbref())) + ".") + tostr(ref[3]));
.echo(code);
.echo(".");
.