diff options
Diffstat (limited to 'unix/uxpsusan.c')
-rw-r--r-- | unix/uxpsusan.c | 422 |
1 files changed, 0 insertions, 422 deletions
diff --git a/unix/uxpsusan.c b/unix/uxpsusan.c deleted file mode 100644 index c60728ce..00000000 --- a/unix/uxpsusan.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * 'psusan': Pseudo Ssh for Untappable, Separately Authenticated Networks - * - * This is a standalone application that speaks on its standard I/O - * (or a listening Unix-domain socket) the server end of the bare - * ssh-connection protocol used by PuTTY's connection sharing. - * - * The idea of this tool is that you can use it to communicate across - * any 8-bit-clean data channel between two inconveniently separated - * domains, provided the channel is already (as the name suggests) - * adequately secured against eavesdropping and modification and - * already authenticated as the right user. - * - * If you're sitting at one end of such a channel and want to type - * commands into the other end, the most obvious thing to do is to run - * a terminal session directly over it. But if you run psusan at one - * end, and a PuTTY (or compatible) client at the other end, then you - * not only get a single terminal session: you get all the other SSH - * amenities, like the ability to spawn extra terminal sessions, - * forward ports or X11 connections, even forward an SSH agent. - * - * There are a surprising number of channels of that kind; see the man - * page for some examples. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <assert.h> -#include <stdarg.h> -#include <signal.h> -#include <unistd.h> -#include <fcntl.h> -#include <termios.h> -#include <pwd.h> -#include <sys/ioctl.h> -#include <sys/time.h> - -#include "putty.h" -#include "mpint.h" -#include "ssh.h" -#include "sshserver.h" - -const char *const appname = "psusan"; - -void modalfatalbox(const char *p, ...) -{ - va_list ap; - fprintf(stderr, "FATAL ERROR: "); - va_start(ap, p); - vfprintf(stderr, p, ap); - va_end(ap); - fputc('\n', stderr); - exit(1); -} -void nonfatal(const char *p, ...) -{ - va_list ap; - fprintf(stderr, "ERROR: "); - va_start(ap, p); - vfprintf(stderr, p, ap); - va_end(ap); - fputc('\n', stderr); -} - -char *platform_default_s(const char *name) -{ - return NULL; -} - -bool platform_default_b(const char *name, bool def) -{ - return def; -} - -int platform_default_i(const char *name, int def) -{ - return def; -} - -FontSpec *platform_default_fontspec(const char *name) -{ - return fontspec_new(""); -} - -Filename *platform_default_filename(const char *name) -{ - return filename_from_str(""); -} - -char *x_get_default(const char *key) -{ - return NULL; /* this is a stub */ -} - -void old_keyfile_warning(void) { } - -void timer_change_notify(unsigned long next) -{ -} - -char *platform_get_x_display(void) { return NULL; } - -void make_unix_sftp_filehandle_key(void *vdata, size_t size) -{ - /* psusan runs without a random number generator, so we can't make - * this up by random_read. Fortunately, psusan is also - * non-adversarial, so it's safe to generate this trivially. */ - unsigned char *data = (unsigned char *)vdata; - for (size_t i = 0; i < size; i++) - data[i] = (unsigned)rand() / ((unsigned)RAND_MAX / 256); -} - -static bool verbose; - -struct server_instance { - unsigned id; - LogPolicy logpolicy; -}; - -static void log_to_stderr(unsigned id, const char *msg) -{ - if (!verbose) - return; - if (id != (unsigned)-1) - fprintf(stderr, "#%u: ", id); - fputs(msg, stderr); - fputc('\n', stderr); - fflush(stderr); -} - -static void server_eventlog(LogPolicy *lp, const char *event) -{ - struct server_instance *inst = container_of( - lp, struct server_instance, logpolicy); - if (verbose) - log_to_stderr(inst->id, event); -} - -static void server_logging_error(LogPolicy *lp, const char *event) -{ - struct server_instance *inst = container_of( - lp, struct server_instance, logpolicy); - log_to_stderr(inst->id, event); /* unconditional */ -} - -static int server_askappend( - LogPolicy *lp, Filename *filename, - void (*callback)(void *ctx, int result), void *ctx) -{ - return 2; /* always overwrite (FIXME: could make this a cmdline option) */ -} - -static const LogPolicyVtable server_logpolicy_vt = { - .eventlog = server_eventlog, - .askappend = server_askappend, - .logging_error = server_logging_error, - .verbose = null_lp_verbose_no, -}; - -static void show_help(FILE *fp) -{ - fputs("usage: psusan [options]\n" - "options: --listen SOCKETPATH listen for connections on a Unix-domain socket\n" - " --listen-once (with --listen) stop after one connection\n" - " --verbose print log messages to standard error\n" - " --sessiondir DIR cwd for session subprocess (default $HOME)\n" - " --sshlog FILE write ssh-connection packet log to FILE\n" - " --sshrawlog FILE write packets and raw data log to FILE\n" - "also: psusan --help show this text\n" - " psusan --version show version information\n", fp); -} - -static void show_version_and_exit(void) -{ - char *buildinfo_text = buildinfo("\n"); - printf("%s: %s\n%s\n", appname, ver, buildinfo_text); - sfree(buildinfo_text); - exit(0); -} - -const bool buildinfo_gtk_relevant = false; - -static bool listening = false, listen_once = false; -static bool finished = false; -void server_instance_terminated(LogPolicy *lp) -{ - struct server_instance *inst = container_of( - lp, struct server_instance, logpolicy); - - if (listening && !listen_once) { - log_to_stderr(inst->id, "connection terminated"); - } else { - finished = true; - } - - sfree(inst); -} - -bool psusan_continue(void *ctx, bool fd, bool cb) -{ - return !finished; -} - -static bool longoptarg(const char *arg, const char *expected, - const char **val, int *argcp, char ***argvp) -{ - int len = strlen(expected); - if (memcmp(arg, expected, len)) - return false; - if (arg[len] == '=') { - *val = arg + len + 1; - return true; - } else if (arg[len] == '\0') { - if (--*argcp > 0) { - *val = *++*argvp; - return true; - } else { - fprintf(stderr, "%s: option %s expects an argument\n", - appname, expected); - exit(1); - } - } - return false; -} - -static bool longoptnoarg(const char *arg, const char *expected) -{ - int len = strlen(expected); - if (memcmp(arg, expected, len)) - return false; - if (arg[len] == '=') { - fprintf(stderr, "%s: option %s expects no argument\n", - appname, expected); - exit(1); - } else if (arg[len] == '\0') { - return true; - } - return false; -} - -struct server_config { - Conf *conf; - const SshServerConfig *ssc; - - unsigned next_id; - - Socket *listening_socket; - Plug listening_plug; -}; - -static Plug *server_conn_plug( - struct server_config *cfg, struct server_instance **inst_out) -{ - struct server_instance *inst = snew(struct server_instance); - - memset(inst, 0, sizeof(*inst)); - - inst->id = cfg->next_id++; - inst->logpolicy.vt = &server_logpolicy_vt; - - if (inst_out) - *inst_out = inst; - - return ssh_server_plug( - cfg->conf, cfg->ssc, NULL, 0, NULL, NULL, - &inst->logpolicy, &unix_live_sftpserver_vt); -} - -static void server_log(Plug *plug, PlugLogType type, SockAddr *addr, int port, - const char *error_msg, int error_code) -{ - log_to_stderr(-1, error_msg); -} - -static void server_closing(Plug *plug, const char *error_msg, int error_code, - bool calling_back) -{ - log_to_stderr(-1, error_msg); -} - -static int server_accepting(Plug *p, accept_fn_t constructor, accept_ctx_t ctx) -{ - struct server_config *cfg = container_of( - p, struct server_config, listening_plug); - Socket *s; - const char *err; - - struct server_instance *inst; - - if (listen_once) { - if (!cfg->listening_socket) /* in case of rapid double-accept */ - return 1; - sk_close(cfg->listening_socket); - cfg->listening_socket = NULL; - } - - Plug *plug = server_conn_plug(cfg, &inst); - s = constructor(ctx, plug); - if ((err = sk_socket_error(s)) != NULL) - return 1; - - SocketPeerInfo *pi = sk_peer_info(s); - - char *msg = dupprintf("new connection from %s", pi->log_text); - log_to_stderr(inst->id, msg); - sfree(msg); - sk_free_peer_info(pi); - - sk_set_frozen(s, false); - ssh_server_start(plug, s); - return 0; -} - -static const PlugVtable server_plugvt = { - .log = server_log, - .closing = server_closing, - .accepting = server_accepting, -}; - -unsigned auth_methods(AuthPolicy *ap) -{ return 0; } -bool auth_none(AuthPolicy *ap, ptrlen username) -{ return false; } -int auth_password(AuthPolicy *ap, ptrlen username, ptrlen password, - ptrlen *new_password_opt) -{ return 0; } -bool auth_publickey(AuthPolicy *ap, ptrlen username, ptrlen public_blob) -{ return false; } -RSAKey *auth_publickey_ssh1( - AuthPolicy *ap, ptrlen username, mp_int *rsa_modulus) -{ return NULL; } -AuthKbdInt *auth_kbdint_prompts(AuthPolicy *ap, ptrlen username) -{ return NULL; } -int auth_kbdint_responses(AuthPolicy *ap, const ptrlen *responses) -{ return -1; } -char *auth_ssh1int_challenge(AuthPolicy *ap, unsigned method, ptrlen username) -{ return NULL; } -bool auth_ssh1int_response(AuthPolicy *ap, ptrlen response) -{ return false; } -bool auth_successful(AuthPolicy *ap, ptrlen username, unsigned method) -{ return false; } - -int main(int argc, char **argv) -{ - const char *listen_socket = NULL; - - SshServerConfig ssc; - - Conf *conf = make_ssh_server_conf(); - - memset(&ssc, 0, sizeof(ssc)); - - ssc.application_name = "PSUSAN"; - ssc.session_starting_dir = getenv("HOME"); - ssc.bare_connection = true; - - while (--argc > 0) { - const char *arg = *++argv; - const char *val; - - if (longoptnoarg(arg, "--help")) { - show_help(stdout); - exit(0); - } else if (longoptnoarg(arg, "--version")) { - show_version_and_exit(); - } else if (longoptnoarg(arg, "--verbose") || !strcmp(arg, "-v")) { - verbose = true; - } else if (longoptarg(arg, "--sessiondir", &val, &argc, &argv)) { - ssc.session_starting_dir = val; - } else if (longoptarg(arg, "--sshlog", &val, &argc, &argv) || - longoptarg(arg, "-sshlog", &val, &argc, &argv)) { - Filename *logfile = filename_from_str(val); - conf_set_filename(conf, CONF_logfilename, logfile); - filename_free(logfile); - conf_set_int(conf, CONF_logtype, LGTYP_PACKETS); - conf_set_int(conf, CONF_logxfovr, LGXF_OVR); - } else if (longoptarg(arg, "--sshrawlog", &val, &argc, &argv) || - longoptarg(arg, "-sshrawlog", &val, &argc, &argv)) { - Filename *logfile = filename_from_str(val); - conf_set_filename(conf, CONF_logfilename, logfile); - filename_free(logfile); - conf_set_int(conf, CONF_logtype, LGTYP_SSHRAW); - conf_set_int(conf, CONF_logxfovr, LGXF_OVR); - } else if (longoptarg(arg, "--listen", &val, &argc, &argv)) { - listen_socket = val; - } else if (!strcmp(arg, "--listen-once")) { - listen_once = true; - } else { - fprintf(stderr, "%s: unrecognised option '%s'\n", appname, arg); - exit(1); - } - } - - sk_init(); - uxsel_init(); - - struct server_config scfg; - scfg.conf = conf; - scfg.ssc = &ssc; - scfg.next_id = 0; - - if (listen_socket) { - listening = true; - scfg.listening_plug.vt = &server_plugvt; - SockAddr *addr = unix_sock_addr(listen_socket); - scfg.listening_socket = new_unix_listener(addr, &scfg.listening_plug); - char *msg = dupprintf("listening on Unix socket %s", listen_socket); - log_to_stderr(-1, msg); - sfree(msg); - } else { - struct server_instance *inst; - Plug *plug = server_conn_plug(&scfg, &inst); - ssh_server_start(plug, make_fd_socket(0, 1, -1, plug)); - log_to_stderr(inst->id, "running directly on stdio"); - } - - cli_main_loop(cliloop_no_pw_setup, cliloop_no_pw_check, - psusan_continue, NULL); - - return 0; -} |