Commit 4cd192c4 authored by Niels Möller's avatar Niels Möller
Browse files

(main): Reorganization, do more work before the work,

including reading host keys and binding sockets directly in main.
Moved the daemonization later, so that the forground process
doesn't exit until after the ports are bound.

Rev: src/lshd.c:1.152
parent 196cef2c
...@@ -192,10 +192,7 @@ const char *argp_program_bug_address = BUG_ADDRESS; ...@@ -192,10 +192,7 @@ const char *argp_program_bug_address = BUG_ADDRESS;
(corefile . int) (corefile . int)
(pid_file . "const char *") (pid_file . "const char *")
; -1 means use pid file iff we're in daemonic mode ; -1 means use pid file iff we're in daemonic mode
(use_pid_file . int) (use_pid_file . int)))
; Resources that should be killed when SIGHUP is received,
; or when the program exits.
(resources object resource_list)))
*/ */
static void static void
...@@ -276,11 +273,6 @@ make_lshd_options(void) ...@@ -276,11 +273,6 @@ make_lshd_options(void)
self->use_pid_file = -1; self->use_pid_file = -1;
self->corefile = 0; self->corefile = 0;
self->resources = make_resource_list();
/* Not strictly needed for gc, but makes sure the
* resource list is killed properly by gc_final. */
gc_global(&self->resources->super);
return self; return self;
} }
...@@ -358,7 +350,7 @@ make_pid_file_resource(const char *file) ...@@ -358,7 +350,7 @@ make_pid_file_resource(const char *file)
(name sighup_close_callback) (name sighup_close_callback)
(super lsh_callback) (super lsh_callback)
(vars (vars
(resources object resource_list))) (resource object resource)))
*/ */
static void static void
...@@ -368,7 +360,7 @@ do_sighup_close_callback(struct lsh_callback *s) ...@@ -368,7 +360,7 @@ do_sighup_close_callback(struct lsh_callback *s)
unsigned nfiles; unsigned nfiles;
werror("SIGHUP received.\n"); werror("SIGHUP received.\n");
KILL_RESOURCE_LIST(self->resources); KILL_RESOURCE(self->resource);
nfiles = io_nfiles(); nfiles = io_nfiles();
...@@ -378,15 +370,16 @@ do_sighup_close_callback(struct lsh_callback *s) ...@@ -378,15 +370,16 @@ do_sighup_close_callback(struct lsh_callback *s)
} }
static struct lsh_callback * static struct lsh_callback *
make_sighup_close_callback(struct lshd_options *options) make_sighup_close_callback(struct resource *resource)
{ {
NEW(sighup_close_callback, self); NEW(sighup_close_callback, self);
self->super.f = do_sighup_close_callback; self->super.f = do_sighup_close_callback;
self->resources = options->resources; self->resource = resource;
return &self->super; return &self->super;
} }
# if 0
/* (close_on_sighup options file) */ /* (close_on_sighup options file) */
DEFINE_COMMAND2(close_on_sighup) DEFINE_COMMAND2(close_on_sighup)
(struct command_2 *ignored UNUSED, (struct command_2 *ignored UNUSED,
...@@ -426,7 +419,7 @@ DEFINE_COMMAND(options2tcp_wrapper) ...@@ -426,7 +419,7 @@ DEFINE_COMMAND(options2tcp_wrapper)
#endif /* WITH_TCPWRAPPERS */ #endif /* WITH_TCPWRAPPERS */
COMMAND_RETURN(c, &io_log_peer_command); COMMAND_RETURN(c, &io_log_peer_command);
} }
#endif
static const struct argp_option static const struct argp_option
main_options[] = main_options[] =
...@@ -919,7 +912,7 @@ main_argp = ...@@ -919,7 +912,7 @@ main_argp =
}; };
/* GABA: /* ;; GABA:
(expr (expr
(name make_lshd_listen) (name make_lshd_listen)
(params (params
...@@ -939,11 +932,28 @@ main_argp = ...@@ -939,11 +932,28 @@ main_argp =
(options2local options) )))))) (options2local options) ))))))
*/ */
/* GABA:
(expr
(name lshd_listen_callback)
(params
(handshake object handshake_info)
(kexinit object make_kexinit)
(keys object alist)
(logger object command)
(services object command) )
(expr (lambda (lv)
(services (connection_handshake
handshake
kexinit
keys
(logger lv))))))
*/
/* Invoked when starting the ssh-connection service */ /* Invoked when starting the ssh-connection service */
/* GABA: /* GABA:
(expr (expr
(name make_lshd_connection_service) (name lshd_connection_service)
(params (params
(hooks object object_list)) (hooks object object_list))
(expr (expr
...@@ -973,11 +983,135 @@ static struct lsh_callback ...@@ -973,11 +983,135 @@ static struct lsh_callback
sigterm_handler = { STATIC_HEADER, do_terminate_callback }; sigterm_handler = { STATIC_HEADER, do_terminate_callback };
static void static void
install_signal_handlers(struct lshd_options *options) install_signal_handlers(struct resource *resource)
{ {
io_signal_handler(SIGTERM, &sigterm_handler); io_signal_handler(SIGTERM, &sigterm_handler);
io_signal_handler(SIGHUP, io_signal_handler(SIGHUP,
make_sighup_close_callback(options)); make_sighup_close_callback(resource));
}
static struct command *
make_lshd_connection_service(struct lshd_options *options)
{
/* Commands to be invoked on the connection */
/* FIXME: Use a queue instead. */
struct object_list *connection_hooks;
struct command *session_setup;
/* Supported channel requests */
struct alist *supported_channel_requests
= make_alist(2,
ATOM_SHELL, &shell_request_handler,
ATOM_EXEC, &exec_request_handler,
-1);
#if WITH_PTY_SUPPORT
if (options->with_pty)
{
ALIST_SET(supported_channel_requests,
ATOM_PTY_REQ, &pty_request_handler.super);
ALIST_SET(supported_channel_requests,
ATOM_WINDOW_CHANGE, &window_change_request_handler.super);
}
#endif /* WITH_PTY_SUPPORT */
#if WITH_X11_FORWARD
if (options->with_x11_forward)
ALIST_SET(supported_channel_requests,
ATOM_X11_REQ, &x11_req_handler.super);
#endif /* WITH_X11_FORWARD */
if (options->subsystems)
ALIST_SET(supported_channel_requests,
ATOM_SUBSYSTEM,
&make_subsystem_handler(options->subsystems)->super);
session_setup = make_install_fix_channel_open_handler
(ATOM_SESSION, make_open_session(supported_channel_requests));
#if WITH_TCP_FORWARD
if (options->with_tcpip_forward)
connection_hooks = make_object_list
(4,
session_setup,
make_tcpip_forward_hook(),
make_install_fix_global_request_handler
(ATOM_CANCEL_TCPIP_FORWARD, &tcpip_cancel_forward),
make_direct_tcpip_hook(),
-1);
else
#endif
connection_hooks
= make_object_list (1, session_setup, -1);
{
CAST_SUBTYPE(command, connection_service,
lshd_connection_service(connection_hooks));
return connection_service;
}
}
static struct io_callback *
make_lshd_listen_callback(struct lshd_options *options,
struct alist *keys,
struct command *service)
{
struct int_list *hostkey_algorithms;
struct make_kexinit *kexinit;
struct command *logger;
/* Include only hostkey algorithms that we have keys for. */
hostkey_algorithms
= filter_algorithms(keys,
options->super.hostkey_algorithms);
if (!hostkey_algorithms)
{
werror("No hostkey algorithms advertised.\n");
hostkey_algorithms = make_int_list(1, ATOM_NONE, -1);
}
kexinit = make_simple_kexinit(options->random,
options->kex_algorithms,
hostkey_algorithms,
options->super.crypto_algorithms,
options->super.mac_algorithms,
options->super.compression_algorithms,
make_int_list(0, -1));
if (options->tcp_wrapper_name)
logger = make_tcp_wrapper
(make_string(options->tcp_wrapper_name),
make_string(options->tcp_wrapper_message
? options->tcp_wrapper_message : ""));
else
logger = &io_log_peer_command;
{
CAST_SUBTYPE(command, server_callback,
lshd_listen_callback
(make_handshake_info(CONNECTION_SERVER,
"lsh - a free ssh",
NULL,
SSH_MAX_PACKET,
options->random,
options->super.algorithms,
options->sshd1),
kexinit,
keys,
logger,
make_offer_service
(make_alist
(1,
ATOM_SSH_USERAUTH,
make_userauth_service(options->userauth_methods,
options->userauth_algorithms,
make_alist(1, ATOM_SSH_CONNECTION,
service,-1)),
-1))));
return make_listen_callback(server_callback, options->e);
}
} }
int int
...@@ -985,6 +1119,15 @@ main(int argc, char **argv) ...@@ -985,6 +1119,15 @@ main(int argc, char **argv)
{ {
struct lshd_options *options; struct lshd_options *options;
/* Resources that should be killed when SIGHUP is received,
* or when the program exits. */
struct resource_list *resources = make_resource_list();
/* Hostkeys */
struct alist *keys = make_alist(0, -1);
struct resource *fds;
#if HAVE_SETRLIMIT && HAVE_SYS_RESOURCE_H #if HAVE_SETRLIMIT && HAVE_SYS_RESOURCE_H
/* Try to increase max number of open files, ignore any error */ /* Try to increase max number of open files, ignore any error */
...@@ -996,6 +1139,10 @@ main(int argc, char **argv) ...@@ -996,6 +1139,10 @@ main(int argc, char **argv)
setrlimit(RLIMIT_NOFILE, &r); setrlimit(RLIMIT_NOFILE, &r);
#endif #endif
/* Not strictly needed for gc, but makes sure the
* resource list is killed properly by gc_final. */
gc_global(&resources->super);
io_init(); io_init();
/* For filtering messages. Could perhaps also be used when converting /* For filtering messages. Could perhaps also be used when converting
...@@ -1005,18 +1152,26 @@ main(int argc, char **argv) ...@@ -1005,18 +1152,26 @@ main(int argc, char **argv)
/* FIXME: Choose character set depending on the locale */ /* FIXME: Choose character set depending on the locale */
set_local_charset(CHARSET_LATIN1); set_local_charset(CHARSET_LATIN1);
install_signal_handlers(&resources->super);
options = make_lshd_options(); options = make_lshd_options();
if (!options) if (!options)
return EXIT_FAILURE; return EXIT_FAILURE;
install_signal_handlers(options);
trace("Parsing options...\n"); trace("Parsing options...\n");
argp_parse(&main_argp, argc, argv, 0, NULL, options); argp_parse(&main_argp, argc, argv, 0, NULL, options);
trace("Parsing options... done\n"); trace("Parsing options... done\n");
if (options->daemonic && !options->no_syslog)
{
#if HAVE_SYSLOG
set_error_syslog("lshd");
#else /* !HAVE_SYSLOG */
werror("lshd: No syslog. Further messages will be directed to /dev/null.\n");
#endif /* !HAVE_SYSLOG */
}
if (!options->corefile && !daemon_disable_core()) if (!options->corefile && !daemon_disable_core())
{ {
werror("Disabling of core dumps failed.\n"); werror("Disabling of core dumps failed.\n");
...@@ -1028,6 +1183,22 @@ main(int argc, char **argv) ...@@ -1028,6 +1183,22 @@ main(int argc, char **argv)
werror("Failed to initialize randomness generator.\n"); werror("Failed to initialize randomness generator.\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!read_host_key(options->hostkey, options->signature_algorithms, keys))
return EXIT_FAILURE;
fds = io_listen_list(options->local,
make_lshd_listen_callback
(options, keys,
make_lshd_connection_service(options)),
options->e);
if (!fds)
{
werror("Could not bind any address.\n");
return EXIT_FAILURE;
}
remember_resource(resources, fds);
if (options->daemonic) if (options->daemonic)
{ {
...@@ -1056,12 +1227,6 @@ main(int argc, char **argv) ...@@ -1056,12 +1227,6 @@ main(int argc, char **argv)
} }
else else
{ {
#if HAVE_SYSLOG
set_error_syslog("lshd");
#else /* !HAVE_SYSLOG */
werror("lshd: No syslog. Further messages will be directed to /dev/null.\n");
#endif /* !HAVE_SYSLOG */
switch (daemon_init()) switch (daemon_init())
{ {
case 0: case 0:
...@@ -1082,7 +1247,7 @@ main(int argc, char **argv) ...@@ -1082,7 +1247,7 @@ main(int argc, char **argv)
if (options->use_pid_file) if (options->use_pid_file)
{ {
if (daemon_pidfile(options->pid_file)) if (daemon_pidfile(options->pid_file))
remember_resource(options->resources, remember_resource(resources,
make_pid_file_resource(options->pid_file)); make_pid_file_resource(options->pid_file));
else else
{ {
...@@ -1090,100 +1255,6 @@ main(int argc, char **argv) ...@@ -1090,100 +1255,6 @@ main(int argc, char **argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
{
/* Commands to be invoked on the connection */
/* FIXME: Use a queue instead. */
struct object_list *connection_hooks;
struct command *session_setup;
/* Supported channel requests */
struct alist *supported_channel_requests
= make_alist(2,
ATOM_SHELL, &shell_request_handler,
ATOM_EXEC, &exec_request_handler,
-1);
#if WITH_PTY_SUPPORT
if (options->with_pty)
{
ALIST_SET(supported_channel_requests,
ATOM_PTY_REQ, &pty_request_handler.super);
ALIST_SET(supported_channel_requests,
ATOM_WINDOW_CHANGE, &window_change_request_handler.super);
}
#endif /* WITH_PTY_SUPPORT */
#if WITH_X11_FORWARD
if (options->with_x11_forward)
ALIST_SET(supported_channel_requests,
ATOM_X11_REQ, &x11_req_handler.super);
#endif /* WITH_X11_FORWARD */
if (options->subsystems)
ALIST_SET(supported_channel_requests,
ATOM_SUBSYSTEM,
&make_subsystem_handler(options->subsystems)->super);
session_setup = make_install_fix_channel_open_handler
(ATOM_SESSION, make_open_session(supported_channel_requests));
#if WITH_TCP_FORWARD
if (options->with_tcpip_forward)
connection_hooks = make_object_list
(4,
session_setup,
make_tcpip_forward_hook(),
make_install_fix_global_request_handler
(ATOM_CANCEL_TCPIP_FORWARD, &tcpip_cancel_forward),
make_direct_tcpip_hook(),
-1);
else
#endif
connection_hooks
= make_object_list (1, session_setup, -1);
{
CAST_SUBTYPE(command, connection_service,
make_lshd_connection_service(connection_hooks));
CAST_SUBTYPE(command, server_listen,
make_lshd_listen
(make_handshake_info(CONNECTION_SERVER,
"lsh - a free ssh",
NULL,
SSH_MAX_PACKET,
options->random,
options->super.algorithms,
options->sshd1),
make_simple_kexinit
(options->random,
options->kex_algorithms,
options->super.hostkey_algorithms,
options->super.crypto_algorithms,
options->super.mac_algorithms,
options->super.compression_algorithms,
make_int_list(0, -1)),
make_offer_service
(make_alist
(1,
ATOM_SSH_USERAUTH,
make_userauth_service(options->userauth_methods,
options->userauth_algorithms,
make_alist(1, ATOM_SSH_CONNECTION,
connection_service,-1)),
-1))));
static const struct report_exception_info report =
STATIC_REPORT_EXCEPTION_INFO(EXC_IO, EXC_IO,
"lshd: ");
COMMAND_CALL(server_listen, options,
&discard_continuation,
make_report_exception_handler
(&report,
options->e,
HANDLER_CONTEXT));
}
}
io_run(); io_run();
......
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