From 7f1591054198e6633f7ed2b1f79d8ed0826df21b Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Sun, 4 Mar 2018 14:57:18 +0800 Subject: get rid of unused packet_type in encrypted write queue --- common-session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common-session.c') diff --git a/common-session.c b/common-session.c index 037a78d..41bf5b3 100644 --- a/common-session.c +++ b/common-session.c @@ -346,7 +346,7 @@ void session_cleanup() { void send_session_identification() { buffer *writebuf = buf_new(strlen(LOCAL_IDENT "\r\n") + 1); buf_putbytes(writebuf, (const unsigned char *) LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n")); - writebuf_enqueue(writebuf, 0); + writebuf_enqueue(writebuf); } static void read_session_identification() { -- cgit v1.2.3 From a60725740b65be8679afe612f7fec2639ed0eab7 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 6 Mar 2018 21:51:51 +0800 Subject: workaround memory sanitizer FD_ZERO false positives --- common-session.c | 11 ++++++----- dbrandom.c | 2 +- dbutil.h | 7 +++++++ fuzz-wrapfd.c | 6 ++++-- svr-main.c | 2 +- sysoptions.h | 11 +++++++++++ 6 files changed, 30 insertions(+), 9 deletions(-) (limited to 'common-session.c') diff --git a/common-session.c b/common-session.c index 41bf5b3..96dd4dc 100644 --- a/common-session.c +++ b/common-session.c @@ -152,8 +152,9 @@ void session_loop(void(*loophandler)(void)) { timeout.tv_sec = select_timeout(); timeout.tv_usec = 0; - FD_ZERO(&writefd); - FD_ZERO(&readfd); + DROPBEAR_FD_ZERO(&writefd); + DROPBEAR_FD_ZERO(&readfd); + dropbear_assert(ses.payload == NULL); /* We get woken up when signal handlers write to this pipe. @@ -204,8 +205,8 @@ void session_loop(void(*loophandler)(void)) { * want to iterate over channels etc for reading, to handle * server processes exiting etc. * We don't want to read/write FDs. */ - FD_ZERO(&writefd); - FD_ZERO(&readfd); + DROPBEAR_FD_ZERO(&writefd); + DROPBEAR_FD_ZERO(&readfd); } /* We'll just empty out the pipe if required. We don't do @@ -406,7 +407,7 @@ static int ident_readln(int fd, char* buf, int count) { return -1; } - FD_ZERO(&fds); + DROPBEAR_FD_ZERO(&fds); /* select since it's a non-blocking fd */ diff --git a/dbrandom.c b/dbrandom.c index 838f8ca..0a55bc5 100644 --- a/dbrandom.c +++ b/dbrandom.c @@ -88,7 +88,7 @@ process_file(hash_state *hs, const char *filename, timeout.tv_sec = 2; timeout.tv_usec = 0; - FD_ZERO(&read_fds); + DROPBEAR_FD_ZERO(&read_fds); FD_SET(readfd, &read_fds); res = select(readfd + 1, &read_fds, NULL, NULL, &timeout); if (res == 0) diff --git a/dbutil.h b/dbutil.h index 7d1c3e1..7cb9d68 100644 --- a/dbutil.h +++ b/dbutil.h @@ -88,4 +88,11 @@ char * expand_homedir_path(const char *inpath); void fsync_parent_dir(const char* fn); +#if DROPBEAR_MSAN +/* FD_ZERO seems to leave some memory uninitialized. clear it to avoid false positives */ +#define DROPBEAR_FD_ZERO(fds) do { memset((fds), 0x0, sizeof(fd_set)); FD_ZERO(fds); } while(0) +#else +#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds) +#endif + #endif /* DROPBEAR_DBUTIL_H_ */ diff --git a/fuzz-wrapfd.c b/fuzz-wrapfd.c index 313a110..ed8968a 100644 --- a/fuzz-wrapfd.c +++ b/fuzz-wrapfd.c @@ -2,6 +2,8 @@ #include "includes.h" #include "fuzz-wrapfd.h" +#include "dbutil.h" + #include "fuzz.h" #define IOWRAP_MAXFD (FD_SETSIZE-1) @@ -195,7 +197,7 @@ int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds, nset++; } } - FD_ZERO(readfds); + DROPBEAR_FD_ZERO(readfds); if (nset > 0) { /* set one */ @@ -222,7 +224,7 @@ int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds, nset++; } } - FD_ZERO(writefds); + DROPBEAR_FD_ZERO(writefds); /* set one */ if (nset > 0) { diff --git a/svr-main.c b/svr-main.c index 6f3144b..0a39b70 100644 --- a/svr-main.c +++ b/svr-main.c @@ -178,7 +178,7 @@ static void main_noinetd() { /* incoming connection select loop */ for(;;) { - FD_ZERO(&fds); + DROPBEAR_FD_ZERO(&fds); /* listening sockets */ for (i = 0; i < listensockcount; i++) { diff --git a/sysoptions.h b/sysoptions.h index 0028199..942e724 100644 --- a/sysoptions.h +++ b/sysoptions.h @@ -318,4 +318,15 @@ If you test it please contact the Dropbear author */ #define DROPBEAR_TRACKING_MALLOC (DROPBEAR_FUZZ) +/* Used to work around Memory Sanitizer false positives */ +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# define DROPBEAR_MSAN 1 +# endif +#endif +#ifndef DROPBEAR_MSAN +#define DROPBEAR_MSAN 0 +#endif + + /* no include guard for this file */ -- cgit v1.2.3 From 0afcfafbb993c856db65e033569539f66491cc1b Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Wed, 20 Mar 2019 22:57:06 +0800 Subject: Add a sanity check for DROPBEAR_SVR_MULTIUSER==0 mode --- common-session.c | 10 ++++++++++ default_options.h | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'common-session.c') diff --git a/common-session.c b/common-session.c index 96dd4dc..aa31e49 100644 --- a/common-session.c +++ b/common-session.c @@ -68,6 +68,16 @@ void common_session_init(int sock_in, int sock_out) { /* Sets it to lowdelay */ update_channel_prio(); +#if !DROPBEAR_SVR_MULTIUSER + /* A sanity check to prevent an accidental configuration option + leaving multiuser systems exposed */ + errno = 0; + getuid(); + if (errno != ENOSYS) { + dropbear_exit("Non-multiuser Dropbear requires a non-multiuser kernel"); + } +#endif + now = monotonic_now(); ses.connect_time = now; ses.last_packet_time_keepalive_recv = now; diff --git a/default_options.h b/default_options.h index 7365d2c..9000fcc 100644 --- a/default_options.h +++ b/default_options.h @@ -196,7 +196,9 @@ group1 in Dropbear server too */ * authorized_keys file into account */ #define DROPBEAR_SVR_PUBKEY_OPTIONS 1 -/* Disable if your kernel does not have multiple user support */ +/* Set this to 0 if your system does not have multiple user support. + (Linux kernel CONFIG_MULTIUSER option) + The resulting binary will not run on a normal system. */ #define DROPBEAR_SVR_MULTIUSER 1 /* Client authentication options */ -- cgit v1.2.3 From 8c6aaf8d361e95ba3d9b371b86abaae1fd0e436f Mon Sep 17 00:00:00 2001 From: fabriziobertocci Date: Wed, 15 May 2019 09:43:57 -0400 Subject: External Public-Key Authentication API (#72) * Implemented dynamic loading of an external plug-in shared library to delegate public key authentication * Moved conditional compilation of the plugin infrastructure into the configure.ac script to be able to add -ldl to dropbear build only when the flag is enabled * Added tags file to the ignore list * Updated API to have the constructor to return function pointers in the pliugin instance. Added support for passing user name to the checkpubkey function. Added options to the session returned by the plugin and have dropbear to parse and process them * Added -rdynamic to the linker flags when EPKA is enabled * Changed the API to pass a previously created session to the checkPubKey function (created during preauth) * Added documentation to the API * Added parameter addrstring to plugin creation function * Modified the API to retrieve the auth options. Instead of having them as field of the EPKASession struct, they are stored internally (plugin-dependent) in the plugin/session and retrieved through a pointer to a function (in the session) * Changed option string to be a simple char * instead of unsigned char * --- .gitignore | 2 + Makefile.in | 11 +++- common-session.c | 4 ++ configure.ac | 15 ++++++ includes.h | 4 ++ pubkeyapi.h | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ runopts.h | 5 ++ session.h | 15 ++++++ svr-authpubkey.c | 48 +++++++++++++++++- svr-runopts.c | 35 +++++++++++-- svr-session.c | 73 +++++++++++++++++++++++++-- sysoptions.h | 3 ++ 12 files changed, 355 insertions(+), 11 deletions(-) create mode 100644 pubkeyapi.h (limited to 'common-session.c') diff --git a/.gitignore b/.gitignore index ea58cd8..35565f6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.bb *.bbg *.prof +.*.swp /autom4te.cache /config.log /config.status @@ -20,3 +21,4 @@ config.h config.h.in configure default_options_guard.h +tags diff --git a/Makefile.in b/Makefile.in index be2d39e..e363fd9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -80,6 +80,15 @@ else scpobjs=$(SCPOBJS) endif +ifeq (@DROPBEAR_EPKA@, 1) + # rdynamic makes all the global symbols of dropbear available to all the loaded shared libraries + # this allow a plugin to reuse existing crypto/utilities like base64_decode/base64_encode without + # the need to rewrite them. + EPKA_LIBS=-ldl -rdynamic +else + EPKA_LIBS= +endif + VPATH=@srcdir@ srcdir=@srcdir@ @@ -189,7 +198,7 @@ dropbearkey: $(dropbearkeyobjs) dropbearconvert: $(dropbearconvertobjs) dropbear: $(HEADERS) $(LIBTOM_DEPS) Makefile - $(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@ + $(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@ $(EPKA_LIBS) dbclient: $(HEADERS) $(LIBTOM_DEPS) Makefile $(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS) diff --git a/common-session.c b/common-session.c index aa31e49..a6449ca 100644 --- a/common-session.c +++ b/common-session.c @@ -147,6 +147,10 @@ void common_session_init(int sock_in, int sock_out) { ses.allowprivport = 0; +#if DROPBEAR_EPKA + ses.epka_session = NULL; +#endif + TRACE(("leave session_init")) } diff --git a/configure.ac b/configure.ac index 7199d7c..bbbfd02 100644 --- a/configure.ac +++ b/configure.ac @@ -323,6 +323,21 @@ AC_ARG_ENABLE(shadow, ] ) +AC_ARG_ENABLE(epka, + [ --enable-epka Enable support for External Public Key Authentication plug-in], + [ + AC_DEFINE(DROPBEAR_EPKA, 1, External Public Key Authentication) + AC_MSG_NOTICE(Enabling support for External Public Key Authentication) + DROPBEAR_EPKA=1 + ], + [ + AC_DEFINE(DROPBEAR_EPKA, 0, External Public Key Authentication) + DROPBEAR_EPKA=0 + ] + +) +AC_SUBST(DROPBEAR_EPKA) + AC_ARG_ENABLE(fuzz, [ --enable-fuzz Build fuzzing. Not recommended for deployment.], [ diff --git a/includes.h b/includes.h index 246882b..2fa26c4 100644 --- a/includes.h +++ b/includes.h @@ -164,6 +164,10 @@ typedef u_int32_t uint32_t; #include #endif +#if DROPBEAR_EPKA +#include +#endif + #include "fake-rfc2553.h" #include "fuzz.h" diff --git a/pubkeyapi.h b/pubkeyapi.h new file mode 100644 index 0000000..9ca9551 --- /dev/null +++ b/pubkeyapi.h @@ -0,0 +1,151 @@ +/* + * Dropbear - a SSH2 server + * + * Copyright (c) 2002,2003 Matt Johnston + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. */ +#ifndef DROPBEAR_PUBKEY_H +#define DROPBEAR_PUBKEY_H + + +/* External Public Key API (EPKA) Plug-in Interface + * + * See: + * https://github.com/fabriziobertocci/dropbear-epka + * for additional information and examples about this API + * + */ + +struct EPKAInstance; +struct EPKASession; + +/* API VERSION INFORMATION - + * Dropbear will: + * - Reject any plugin with a major version mismatch + * - Load and print a warning if the plugin's minor version is HIGHER than + * dropbear's minor version (assumes properties are added at the end of + * EPKAInstance or EPKASession). This is a case of plugin newer than dropbear. + * - Reject if the plugin minor version is SMALLER than dropbear one (case + * of plugin older than dropbear). + * - Load (with no warnings) if version match. + */ +#define DROPBEAR_EPKA_VERSION_MAJOR 1 +#define DROPBEAR_EPKA_VERSION_MINOR 0 + + +/* Creates an instance of the plugin. + * + * This is the main entry point of the plug-in and should be IMMUTABLE across + * different API versions. Dropbear will check the version number + * returned in the api_version to match the version it understands and reject + * any plugin for which API major version does not match. + * + * If the version MINOR is different, dropbear will allow the plugin to run + * only if: plugin_MINOR > dropbear_MINOR + * + * If plugin_MINOR < dropbeart_MINOR or if the MAJOR version is different + * dropbear will reject the plugin and terminate the execution. + * + * addrstring is the IP address of the client. + * + * Returns NULL in case of failure, otherwise a void * of the instance that need + * to be passed to all the subsequent call to the plugin + */ +typedef struct EPKAInstance *(* PubkeyExtPlugin_newFn)(int verbose, + const char *options, + const char *addrstring); +#define DROPBEAR_PUBKEY_PLUGIN_FNNAME_NEW "plugin_new" + + +/* Validate a client through public key authentication + * + * If session has not been already created, creates it and store it + * in *sessionInOut. + * If session is a non-NULL, it will reuse it. + * + * Returns DROPBEAR_SUCCESS (0) if success or DROPBEAR_FAILURE (-1) if + * authentication fails + */ +typedef int (* PubkeyExtPlugin_checkPubKeyFn)(struct EPKAInstance *pluginInstance, + struct EPKASession **sessionInOut, + const char* algo, + unsigned int algolen, + const unsigned char* keyblob, + unsigned int keybloblen, + const char *username); + +/* Notify the plugin that auth completed (after signature verification) + */ +typedef void (* PubkeyExtPlugin_authSuccessFn)(struct EPKASession *session); + +/* Deletes a session + * TODO: Add a reason why the session is terminated. See svr_dropbear_exit (in svr-session.c) + */ +typedef void (* PubkeyExtPlugin_sessionDeleteFn)(struct EPKASession *session); + +/* Deletes the plugin instance */ +typedef void (* PubkeyExtPlugin_deleteFn)(struct EPKAInstance *pluginInstance); + + +/* The EPKAInstance object - A simple container of the pointer to the functions used + * by Dropbear. + * + * A plug-in can extend it to add its own properties + * + * The instance is created from the call to the plugin_new() function of the + * shared library. + * The delete_plugin function should delete the object. + */ +struct EPKAInstance { + int api_version[2]; /* 0=Major, 1=Minor */ + + PubkeyExtPlugin_checkPubKeyFn checkpubkey; /* mandatory */ + PubkeyExtPlugin_authSuccessFn auth_success; /* optional */ + PubkeyExtPlugin_sessionDeleteFn delete_session; /* mandatory */ + PubkeyExtPlugin_deleteFn delete_plugin; /* mandatory */ +}; + +/***************************************************************************** + * SESSION + ****************************************************************************/ +/* Returns the options from the session. + * The returned buffer will be destroyed when the session is deleted. + * Option buffer string NULL-terminated + */ +typedef char * (* PubkeyExtPlugin_getOptionsFn)(struct EPKASession *session); + + +/* An SSH Session. Created during pre-auth and reused during the authentication. + * The plug-in should delete this object (or any object extending it) from + * the delete_session() function. + * + * Extend it to cache user and authentication information that can be + * reused between pre-auth and auth (and to store whatever session-specific + * variable you need to keep). + * + * Store any optional auth options in the auth_options property of the session. + */ +struct EPKASession { + struct EPKAInstance * plugin_instance; + + PubkeyExtPlugin_getOptionsFn get_options; +}; + +#endif diff --git a/runopts.h b/runopts.h index 31eae1f..f173678 100644 --- a/runopts.h +++ b/runopts.h @@ -125,6 +125,11 @@ typedef struct svr_runopts { char * forced_command; +#if DROPBEAR_EPKA + char *pubkey_plugin; + char *pubkey_plugin_options; +#endif + } svr_runopts; extern svr_runopts svr_opts; diff --git a/session.h b/session.h index 0f77055..efade6e 100644 --- a/session.h +++ b/session.h @@ -38,6 +38,9 @@ #include "chansession.h" #include "dbutil.h" #include "netio.h" +#if DROPBEAR_EPKA +#include "pubkeyapi.h" +#endif void common_session_init(int sock_in, int sock_out); void session_loop(void(*loophandler)(void)) ATTRIB_NORETURN; @@ -216,6 +219,10 @@ struct sshsession { volatile int exitflag; /* set once the ses structure (and cli_ses/svr_ses) have been populated to their initial state */ int init_done; + +#if DROPBEAR_EPKA + struct EPKASession * epka_session; +#endif }; struct serversession { @@ -241,6 +248,14 @@ struct serversession { pid_t server_pid; #endif +#if DROPBEAR_EPKA + /* The shared library handle */ + void *epka_plugin_handle; + + /* The instance created by the plugin_new function */ + struct EPKAInstance *epka_instance; +#endif + }; typedef enum { diff --git a/svr-authpubkey.c b/svr-authpubkey.c index 4f27986..9d70bfb 100644 --- a/svr-authpubkey.c +++ b/svr-authpubkey.c @@ -91,6 +91,7 @@ void svr_auth_pubkey(int valid_user) { sign_key * key = NULL; char* fp = NULL; enum signkey_type type = -1; + int auth_failure = 1; TRACE(("enter pubkeyauth")) @@ -110,9 +111,45 @@ void svr_auth_pubkey(int valid_user) { send_msg_userauth_failure(0, 0); goto out; } - +#if DROPBEAR_EPKA + if (svr_ses.epka_instance != NULL) { + char *options_buf; + if (svr_ses.epka_instance->checkpubkey( + svr_ses.epka_instance, + &ses.epka_session, + algo, + algolen, + keyblob, + keybloblen, + ses.authstate.username) == DROPBEAR_SUCCESS) { + /* Success */ + auth_failure = 0; + + /* Options provided? */ + options_buf = ses.epka_session->get_options(ses.epka_session); + if (options_buf) { + struct buf temp_buf = { + .data = (unsigned char *)options_buf, + .len = strlen(options_buf), + .pos = 0, + .size = 0 + }; + int ret = svr_add_pubkey_options(&temp_buf, 0, "N/A"); + if (ret == DROPBEAR_FAILURE) { + /* Fail immediately as the plugin provided wrong options */ + send_msg_userauth_failure(0, 0); + goto out; + } + } + } + } +#endif /* check if the key is valid */ - if (checkpubkey(algo, algolen, keyblob, keybloblen) == DROPBEAR_FAILURE) { + if (auth_failure) { + auth_failure = checkpubkey(algo, algolen, keyblob, keybloblen) == DROPBEAR_FAILURE; + } + + if (auth_failure) { send_msg_userauth_failure(0, 0); goto out; } @@ -156,6 +193,13 @@ void svr_auth_pubkey(int valid_user) { "Pubkey auth succeeded for '%s' with key %s from %s", ses.authstate.pw_name, fp, svr_ses.addrstring); send_msg_userauth_success(); +#if DROPBEAR_EPKA + if ((ses.epka_session != NULL) && (svr_ses.epka_instance->auth_success != NULL)) { + /* Was authenticated through the external plugin. tell plugin that signature verification was ok */ + svr_ses.epka_instance->auth_success(ses.epka_session); + } +#endif + } else { dropbear_log(LOG_WARNING, "Pubkey auth bad signature for '%s' with key %s from %s", diff --git a/svr-runopts.c b/svr-runopts.c index d6c78df..19ce14c 100644 --- a/svr-runopts.c +++ b/svr-runopts.c @@ -46,16 +46,16 @@ static void printhelp(const char * progname) { "-b bannerfile Display the contents of bannerfile" " before user login\n" " (default: none)\n" - "-r keyfile Specify hostkeys (repeatable)\n" + "-r keyfile Specify hostkeys (repeatable)\n" " defaults: \n" #if DROPBEAR_DSS - " dss %s\n" + " - dss %s\n" #endif #if DROPBEAR_RSA - " rsa %s\n" + " - rsa %s\n" #endif #if DROPBEAR_ECDSA - " ecdsa %s\n" + " - ecdsa %s\n" #endif #if DROPBEAR_DELAY_HOSTKEY "-R Create hostkeys as required\n" @@ -99,6 +99,10 @@ static void printhelp(const char * progname) { "-W (default %d, larger may be faster, max 1MB)\n" "-K (0 is never, default %d, in seconds)\n" "-I (0 is never, default %d, in seconds)\n" +#if DROPBEAR_EPKA + "-A [,]\n" + " Enable external public key auth through \n" +#endif "-V Version\n" #if DEBUG_TRACE "-v verbose (compiled with DEBUG_TRACE)\n" @@ -129,6 +133,9 @@ void svr_getopts(int argc, char ** argv) { char* maxauthtries_arg = NULL; char* keyfile = NULL; char c; +#if DROPBEAR_EPKA + char* pubkey_plugin = NULL; +#endif /* see printhelp() for options */ @@ -156,6 +163,10 @@ void svr_getopts(int argc, char ** argv) { #if DROPBEAR_SVR_REMOTETCPFWD svr_opts.noremotetcp = 0; #endif +#if DROPBEAR_EPKA + svr_opts.pubkey_plugin = NULL; + svr_opts.pubkey_plugin_options = NULL; +#endif #ifndef DISABLE_ZLIB opts.compress_mode = DROPBEAR_COMPRESS_DELAYED; @@ -274,6 +285,11 @@ void svr_getopts(int argc, char ** argv) { case 'u': /* backwards compatibility with old urandom option */ break; +#if DROPBEAR_EPKA + case 'A': + next = &pubkey_plugin; + break; +#endif #if DEBUG_TRACE case 'v': debug_trace = 1; @@ -394,6 +410,17 @@ void svr_getopts(int argc, char ** argv) { if (svr_opts.forced_command) { dropbear_log(LOG_INFO, "Forced command set to '%s'", svr_opts.forced_command); } +#if DROPBEAR_EPKA + if (pubkey_plugin) { + char *args = strchr(pubkey_plugin, ','); + if (args) { + *args='\0'; + ++args; + } + svr_opts.pubkey_plugin = pubkey_plugin; + svr_opts.pubkey_plugin_options = args; + } +#endif } static void addportandaddress(const char* spec) { diff --git a/svr-session.c b/svr-session.c index a816398..3ea7589 100644 --- a/svr-session.c +++ b/svr-session.c @@ -88,6 +88,18 @@ svr_session_cleanup(void) { m_free(svr_ses.remotehost); m_free(svr_ses.childpids); svr_ses.childpidsize = 0; + +#if DROPBEAR_EPKA + if (svr_ses.epka_plugin_handle != NULL) { + if (svr_ses.epka_instance) { + svr_ses.epka_instance->delete_plugin(svr_ses.epka_instance); + svr_ses.epka_instance = NULL; + } + + dlclose(svr_ses.epka_plugin_handle); + svr_ses.epka_plugin_handle = NULL; + } +#endif } void svr_session(int sock, int childpipe) { @@ -101,10 +113,6 @@ void svr_session(int sock, int childpipe) { #if DROPBEAR_VFORK svr_ses.server_pid = getpid(); #endif - svr_authinitialise(); - chaninitialise(svr_chantypes); - svr_chansessinitialise(); - svr_algos_initialise(); /* for logging the remote address */ get_socket_address(ses.sock_in, NULL, NULL, &host, &port, 0); @@ -114,6 +122,56 @@ void svr_session(int sock, int childpipe) { m_free(host); m_free(port); +#if DROPBEAR_EPKA + /* Initializes the EPKA Plugin */ + svr_ses.epka_plugin_handle = NULL; + svr_ses.epka_instance = NULL; + if (svr_opts.pubkey_plugin) { +#if DEBUG_TRACE + const int verbose = debug_trace; +#else + const int verbose = 0; +#endif + PubkeyExtPlugin_newFn pluginConstructor; + + /* RTLD_NOW: fails if not all the symbols are resolved now. Better fail now than at run-time */ + svr_ses.epka_plugin_handle = dlopen(svr_opts.pubkey_plugin, RTLD_NOW); + if (svr_ses.epka_plugin_handle == NULL) { + dropbear_exit("failed to load external pubkey plugin '%s': %s", svr_opts.pubkey_plugin, dlerror()); + } + pluginConstructor = (PubkeyExtPlugin_newFn)dlsym(svr_ses.epka_plugin_handle, DROPBEAR_PUBKEY_PLUGIN_FNNAME_NEW); + if (!pluginConstructor) { + dropbear_exit("plugin constructor method not found in external pubkey plugin"); + } + + /* Create an instance of the plugin */ + svr_ses.epka_instance = pluginConstructor(verbose, svr_opts.pubkey_plugin_options, svr_ses.addrstring); + if (svr_ses.epka_instance == NULL) { + dropbear_exit("external plugin initialization failed"); + } + /* Check if the plugin is compatible */ + if ( (svr_ses.epka_instance->api_version[0] != DROPBEAR_EPKA_VERSION_MAJOR) || + (svr_ses.epka_instance->api_version[1] < DROPBEAR_EPKA_VERSION_MINOR) ) { + dropbear_exit("plugin version check failed: " + "Dropbear=%d.%d, plugin=%d.%d", + DROPBEAR_EPKA_VERSION_MAJOR, DROPBEAR_EPKA_VERSION_MINOR, + svr_ses.epka_instance->api_version[0], svr_ses.epka_instance->api_version[1]); + } + if (svr_ses.epka_instance->api_version[1] > DROPBEAR_EPKA_VERSION_MINOR) { + dropbear_log(LOG_WARNING, "plugin API newer than dropbear API: " + "Dropbear=%d.%d, plugin=%d.%d", + DROPBEAR_EPKA_VERSION_MAJOR, DROPBEAR_EPKA_VERSION_MINOR, + svr_ses.epka_instance->api_version[0], svr_ses.epka_instance->api_version[1]); + } + dropbear_log(LOG_INFO, "successfully loaded and initialized pubkey plugin '%s'", svr_opts.pubkey_plugin); + } +#endif + + svr_authinitialise(); + chaninitialise(svr_chantypes); + svr_chansessinitialise(); + svr_algos_initialise(); + get_socket_address(ses.sock_in, NULL, NULL, &svr_ses.remotehost, NULL, 1); @@ -151,6 +209,13 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) { char fullmsg[300]; int i; +#if DROPBEAR_EPKA + if ((ses.epka_session != NULL)) { + svr_ses.epka_instance->delete_session(ses.epka_session); + } + ses.epka_session = NULL; +#endif + /* Render the formatted exit message */ vsnprintf(exitmsg, sizeof(exitmsg), format, param); diff --git a/sysoptions.h b/sysoptions.h index efb27d8..58604f0 100644 --- a/sysoptions.h +++ b/sysoptions.h @@ -243,6 +243,9 @@ If you test it please contact the Dropbear author */ #error "At least one server authentication type must be enabled. DROPBEAR_SVR_PUBKEY_AUTH and DROPBEAR_SVR_PASSWORD_AUTH are recommended." #endif +#if (DROPBEAR_EPKA && !DROPBEAR_SVR_PUBKEY_AUTH) + #error "You must define DROPBEAR_SVR_PUBKEY_AUTH in order to use External Public Key Authentication (EPKA)" +#endif #if !(DROPBEAR_AES128 || DROPBEAR_3DES || DROPBEAR_AES256 || DROPBEAR_BLOWFISH \ || DROPBEAR_TWOFISH256 || DROPBEAR_TWOFISH128) -- cgit v1.2.3 From fa116e983b4931010e1082dd5c8bf38bbc77718c Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Wed, 15 May 2019 21:59:45 +0800 Subject: Rename EPKA -> Plugin --- Makefile.in | 8 ++++---- common-session.c | 4 ++-- configure.ac | 14 +++++++------- includes.h | 2 +- pubkeyapi.h | 34 +++++++++++++++++----------------- runopts.h | 2 +- session.h | 12 ++++++------ svr-authpubkey.c | 18 +++++++++--------- svr-runopts.c | 10 +++++----- svr-session.c | 54 +++++++++++++++++++++++++++--------------------------- sysoptions.h | 4 ++-- 11 files changed, 81 insertions(+), 81 deletions(-) (limited to 'common-session.c') diff --git a/Makefile.in b/Makefile.in index e363fd9..4bac2f7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -80,13 +80,13 @@ else scpobjs=$(SCPOBJS) endif -ifeq (@DROPBEAR_EPKA@, 1) +ifeq (@DROPBEAR_PLUGIN@, 1) # rdynamic makes all the global symbols of dropbear available to all the loaded shared libraries # this allow a plugin to reuse existing crypto/utilities like base64_decode/base64_encode without # the need to rewrite them. - EPKA_LIBS=-ldl -rdynamic + PLUGIN_LIBS=-ldl -rdynamic else - EPKA_LIBS= + PLUGIN_LIBS= endif VPATH=@srcdir@ @@ -198,7 +198,7 @@ dropbearkey: $(dropbearkeyobjs) dropbearconvert: $(dropbearconvertobjs) dropbear: $(HEADERS) $(LIBTOM_DEPS) Makefile - $(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@ $(EPKA_LIBS) + $(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@ $(PLUGIN_LIBS) dbclient: $(HEADERS) $(LIBTOM_DEPS) Makefile $(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBTOM_LIBS) $(LIBS) diff --git a/common-session.c b/common-session.c index a6449ca..fc0f9a0 100644 --- a/common-session.c +++ b/common-session.c @@ -147,8 +147,8 @@ void common_session_init(int sock_in, int sock_out) { ses.allowprivport = 0; -#if DROPBEAR_EPKA - ses.epka_session = NULL; +#if DROPBEAR_PLUGIN + ses.plugin_session = NULL; #endif TRACE(("leave session_init")) diff --git a/configure.ac b/configure.ac index bbbfd02..9996c34 100644 --- a/configure.ac +++ b/configure.ac @@ -323,20 +323,20 @@ AC_ARG_ENABLE(shadow, ] ) -AC_ARG_ENABLE(epka, - [ --enable-epka Enable support for External Public Key Authentication plug-in], +AC_ARG_ENABLE(plugin, + [ --enable-plugin Enable support for External Public Key Authentication plug-in], [ - AC_DEFINE(DROPBEAR_EPKA, 1, External Public Key Authentication) + AC_DEFINE(DROPBEAR_PLUGIN, 1, External Public Key Authentication) AC_MSG_NOTICE(Enabling support for External Public Key Authentication) - DROPBEAR_EPKA=1 + DROPBEAR_PLUGIN=1 ], [ - AC_DEFINE(DROPBEAR_EPKA, 0, External Public Key Authentication) - DROPBEAR_EPKA=0 + AC_DEFINE(DROPBEAR_PLUGIN, 0, External Public Key Authentication) + DROPBEAR_PLUGIN=0 ] ) -AC_SUBST(DROPBEAR_EPKA) +AC_SUBST(DROPBEAR_PLUGIN) AC_ARG_ENABLE(fuzz, [ --enable-fuzz Build fuzzing. Not recommended for deployment.], diff --git a/includes.h b/includes.h index 2fa26c4..6432d6e 100644 --- a/includes.h +++ b/includes.h @@ -164,7 +164,7 @@ typedef u_int32_t uint32_t; #include #endif -#if DROPBEAR_EPKA +#if DROPBEAR_PLUGIN #include #endif diff --git a/pubkeyapi.h b/pubkeyapi.h index 9ca9551..21b1f24 100644 --- a/pubkeyapi.h +++ b/pubkeyapi.h @@ -33,21 +33,21 @@ * */ -struct EPKAInstance; -struct EPKASession; +struct PluginInstance; +struct PluginSession; /* API VERSION INFORMATION - * Dropbear will: * - Reject any plugin with a major version mismatch * - Load and print a warning if the plugin's minor version is HIGHER than * dropbear's minor version (assumes properties are added at the end of - * EPKAInstance or EPKASession). This is a case of plugin newer than dropbear. + * PluginInstance or PluginSession). This is a case of plugin newer than dropbear. * - Reject if the plugin minor version is SMALLER than dropbear one (case * of plugin older than dropbear). * - Load (with no warnings) if version match. */ -#define DROPBEAR_EPKA_VERSION_MAJOR 1 -#define DROPBEAR_EPKA_VERSION_MINOR 0 +#define DROPBEAR_PLUGIN_VERSION_MAJOR 1 +#define DROPBEAR_PLUGIN_VERSION_MINOR 0 /* Creates an instance of the plugin. @@ -60,7 +60,7 @@ struct EPKASession; * If the version MINOR is different, dropbear will allow the plugin to run * only if: plugin_MINOR > dropbear_MINOR * - * If plugin_MINOR < dropbeart_MINOR or if the MAJOR version is different + * If plugin_MINOR < dropbear_MINOR or if the MAJOR version is different * dropbear will reject the plugin and terminate the execution. * * addrstring is the IP address of the client. @@ -68,7 +68,7 @@ struct EPKASession; * Returns NULL in case of failure, otherwise a void * of the instance that need * to be passed to all the subsequent call to the plugin */ -typedef struct EPKAInstance *(* PubkeyExtPlugin_newFn)(int verbose, +typedef struct PluginInstance *(* PubkeyExtPlugin_newFn)(int verbose, const char *options, const char *addrstring); #define DROPBEAR_PUBKEY_PLUGIN_FNNAME_NEW "plugin_new" @@ -83,8 +83,8 @@ typedef struct EPKAInstance *(* PubkeyExtPlugin_newFn)(int verbose, * Returns DROPBEAR_SUCCESS (0) if success or DROPBEAR_FAILURE (-1) if * authentication fails */ -typedef int (* PubkeyExtPlugin_checkPubKeyFn)(struct EPKAInstance *pluginInstance, - struct EPKASession **sessionInOut, +typedef int (* PubkeyExtPlugin_checkPubKeyFn)(struct PluginInstance *PluginInstance, + struct PluginSession **sessionInOut, const char* algo, unsigned int algolen, const unsigned char* keyblob, @@ -93,18 +93,18 @@ typedef int (* PubkeyExtPlugin_checkPubKeyFn)(struct EPKAInstance *pluginInstanc /* Notify the plugin that auth completed (after signature verification) */ -typedef void (* PubkeyExtPlugin_authSuccessFn)(struct EPKASession *session); +typedef void (* PubkeyExtPlugin_authSuccessFn)(struct PluginSession *session); /* Deletes a session * TODO: Add a reason why the session is terminated. See svr_dropbear_exit (in svr-session.c) */ -typedef void (* PubkeyExtPlugin_sessionDeleteFn)(struct EPKASession *session); +typedef void (* PubkeyExtPlugin_sessionDeleteFn)(struct PluginSession *session); /* Deletes the plugin instance */ -typedef void (* PubkeyExtPlugin_deleteFn)(struct EPKAInstance *pluginInstance); +typedef void (* PubkeyExtPlugin_deleteFn)(struct PluginInstance *PluginInstance); -/* The EPKAInstance object - A simple container of the pointer to the functions used +/* The PluginInstance object - A simple container of the pointer to the functions used * by Dropbear. * * A plug-in can extend it to add its own properties @@ -113,7 +113,7 @@ typedef void (* PubkeyExtPlugin_deleteFn)(struct EPKAInstance *pluginInstance); * shared library. * The delete_plugin function should delete the object. */ -struct EPKAInstance { +struct PluginInstance { int api_version[2]; /* 0=Major, 1=Minor */ PubkeyExtPlugin_checkPubKeyFn checkpubkey; /* mandatory */ @@ -129,7 +129,7 @@ struct EPKAInstance { * The returned buffer will be destroyed when the session is deleted. * Option buffer string NULL-terminated */ -typedef char * (* PubkeyExtPlugin_getOptionsFn)(struct EPKASession *session); +typedef char * (* PubkeyExtPlugin_getOptionsFn)(struct PluginSession *session); /* An SSH Session. Created during pre-auth and reused during the authentication. @@ -142,8 +142,8 @@ typedef char * (* PubkeyExtPlugin_getOptionsFn)(struct EPKASession *session); * * Store any optional auth options in the auth_options property of the session. */ -struct EPKASession { - struct EPKAInstance * plugin_instance; +struct PluginSession { + struct PluginInstance * plugin_instance; PubkeyExtPlugin_getOptionsFn get_options; }; diff --git a/runopts.h b/runopts.h index f173678..6a4a94c 100644 --- a/runopts.h +++ b/runopts.h @@ -125,7 +125,7 @@ typedef struct svr_runopts { char * forced_command; -#if DROPBEAR_EPKA +#if DROPBEAR_PLUGIN char *pubkey_plugin; char *pubkey_plugin_options; #endif diff --git a/session.h b/session.h index efade6e..e436882 100644 --- a/session.h +++ b/session.h @@ -38,7 +38,7 @@ #include "chansession.h" #include "dbutil.h" #include "netio.h" -#if DROPBEAR_EPKA +#if DROPBEAR_PLUGIN #include "pubkeyapi.h" #endif @@ -220,8 +220,8 @@ struct sshsession { /* set once the ses structure (and cli_ses/svr_ses) have been populated to their initial state */ int init_done; -#if DROPBEAR_EPKA - struct EPKASession * epka_session; +#if DROPBEAR_PLUGIN + struct PluginSession * plugin_session; #endif }; @@ -248,12 +248,12 @@ struct serversession { pid_t server_pid; #endif -#if DROPBEAR_EPKA +#if DROPBEAR_PLUGIN /* The shared library handle */ - void *epka_plugin_handle; + void *plugin_handle; /* The instance created by the plugin_new function */ - struct EPKAInstance *epka_instance; + struct PluginInstance *plugin_instance; #endif }; diff --git a/svr-authpubkey.c b/svr-authpubkey.c index 9d70bfb..5c234b9 100644 --- a/svr-authpubkey.c +++ b/svr-authpubkey.c @@ -111,12 +111,12 @@ void svr_auth_pubkey(int valid_user) { send_msg_userauth_failure(0, 0); goto out; } -#if DROPBEAR_EPKA - if (svr_ses.epka_instance != NULL) { +#if DROPBEAR_PLUGIN + if (svr_ses.plugin_instance != NULL) { char *options_buf; - if (svr_ses.epka_instance->checkpubkey( - svr_ses.epka_instance, - &ses.epka_session, + if (svr_ses.plugin_instance->checkpubkey( + svr_ses.plugin_instance, + &ses.plugin_session, algo, algolen, keyblob, @@ -126,7 +126,7 @@ void svr_auth_pubkey(int valid_user) { auth_failure = 0; /* Options provided? */ - options_buf = ses.epka_session->get_options(ses.epka_session); + options_buf = ses.plugin_session->get_options(ses.plugin_session); if (options_buf) { struct buf temp_buf = { .data = (unsigned char *)options_buf, @@ -193,10 +193,10 @@ void svr_auth_pubkey(int valid_user) { "Pubkey auth succeeded for '%s' with key %s from %s", ses.authstate.pw_name, fp, svr_ses.addrstring); send_msg_userauth_success(); -#if DROPBEAR_EPKA - if ((ses.epka_session != NULL) && (svr_ses.epka_instance->auth_success != NULL)) { +#if DROPBEAR_PLUGIN + if ((ses.plugin_session != NULL) && (svr_ses.plugin_instance->auth_success != NULL)) { /* Was authenticated through the external plugin. tell plugin that signature verification was ok */ - svr_ses.epka_instance->auth_success(ses.epka_session); + svr_ses.plugin_instance->auth_success(ses.plugin_session); } #endif diff --git a/svr-runopts.c b/svr-runopts.c index 19ce14c..d7a0d5a 100644 --- a/svr-runopts.c +++ b/svr-runopts.c @@ -99,7 +99,7 @@ static void printhelp(const char * progname) { "-W (default %d, larger may be faster, max 1MB)\n" "-K (0 is never, default %d, in seconds)\n" "-I (0 is never, default %d, in seconds)\n" -#if DROPBEAR_EPKA +#if DROPBEAR_PLUGIN "-A [,]\n" " Enable external public key auth through \n" #endif @@ -133,7 +133,7 @@ void svr_getopts(int argc, char ** argv) { char* maxauthtries_arg = NULL; char* keyfile = NULL; char c; -#if DROPBEAR_EPKA +#if DROPBEAR_PLUGIN char* pubkey_plugin = NULL; #endif @@ -163,7 +163,7 @@ void svr_getopts(int argc, char ** argv) { #if DROPBEAR_SVR_REMOTETCPFWD svr_opts.noremotetcp = 0; #endif -#if DROPBEAR_EPKA +#if DROPBEAR_PLUGIN svr_opts.pubkey_plugin = NULL; svr_opts.pubkey_plugin_options = NULL; #endif @@ -285,7 +285,7 @@ void svr_getopts(int argc, char ** argv) { case 'u': /* backwards compatibility with old urandom option */ break; -#if DROPBEAR_EPKA +#if DROPBEAR_PLUGIN case 'A': next = &pubkey_plugin; break; @@ -410,7 +410,7 @@ void svr_getopts(int argc, char ** argv) { if (svr_opts.forced_command) { dropbear_log(LOG_INFO, "Forced command set to '%s'", svr_opts.forced_command); } -#if DROPBEAR_EPKA +#if DROPBEAR_PLUGIN if (pubkey_plugin) { char *args = strchr(pubkey_plugin, ','); if (args) { diff --git a/svr-session.c b/svr-session.c index 3ea7589..47f36b5 100644 --- a/svr-session.c +++ b/svr-session.c @@ -89,15 +89,15 @@ svr_session_cleanup(void) { m_free(svr_ses.childpids); svr_ses.childpidsize = 0; -#if DROPBEAR_EPKA - if (svr_ses.epka_plugin_handle != NULL) { - if (svr_ses.epka_instance) { - svr_ses.epka_instance->delete_plugin(svr_ses.epka_instance); - svr_ses.epka_instance = NULL; +#if DROPBEAR_PLUGIN + if (svr_ses.plugin_handle != NULL) { + if (svr_ses.plugin_instance) { + svr_ses.plugin_instance->delete_plugin(svr_ses.plugin_instance); + svr_ses.plugin_instance = NULL; } - dlclose(svr_ses.epka_plugin_handle); - svr_ses.epka_plugin_handle = NULL; + dlclose(svr_ses.plugin_handle); + svr_ses.plugin_handle = NULL; } #endif } @@ -122,10 +122,10 @@ void svr_session(int sock, int childpipe) { m_free(host); m_free(port); -#if DROPBEAR_EPKA - /* Initializes the EPKA Plugin */ - svr_ses.epka_plugin_handle = NULL; - svr_ses.epka_instance = NULL; +#if DROPBEAR_PLUGIN + /* Initializes the PLUGIN Plugin */ + svr_ses.plugin_handle = NULL; + svr_ses.plugin_instance = NULL; if (svr_opts.pubkey_plugin) { #if DEBUG_TRACE const int verbose = debug_trace; @@ -135,33 +135,33 @@ void svr_session(int sock, int childpipe) { PubkeyExtPlugin_newFn pluginConstructor; /* RTLD_NOW: fails if not all the symbols are resolved now. Better fail now than at run-time */ - svr_ses.epka_plugin_handle = dlopen(svr_opts.pubkey_plugin, RTLD_NOW); - if (svr_ses.epka_plugin_handle == NULL) { + svr_ses.plugin_handle = dlopen(svr_opts.pubkey_plugin, RTLD_NOW); + if (svr_ses.plugin_handle == NULL) { dropbear_exit("failed to load external pubkey plugin '%s': %s", svr_opts.pubkey_plugin, dlerror()); } - pluginConstructor = (PubkeyExtPlugin_newFn)dlsym(svr_ses.epka_plugin_handle, DROPBEAR_PUBKEY_PLUGIN_FNNAME_NEW); + pluginConstructor = (PubkeyExtPlugin_newFn)dlsym(svr_ses.plugin_handle, DROPBEAR_PUBKEY_PLUGIN_FNNAME_NEW); if (!pluginConstructor) { dropbear_exit("plugin constructor method not found in external pubkey plugin"); } /* Create an instance of the plugin */ - svr_ses.epka_instance = pluginConstructor(verbose, svr_opts.pubkey_plugin_options, svr_ses.addrstring); - if (svr_ses.epka_instance == NULL) { + svr_ses.plugin_instance = pluginConstructor(verbose, svr_opts.pubkey_plugin_options, svr_ses.addrstring); + if (svr_ses.plugin_instance == NULL) { dropbear_exit("external plugin initialization failed"); } /* Check if the plugin is compatible */ - if ( (svr_ses.epka_instance->api_version[0] != DROPBEAR_EPKA_VERSION_MAJOR) || - (svr_ses.epka_instance->api_version[1] < DROPBEAR_EPKA_VERSION_MINOR) ) { + if ( (svr_ses.plugin_instance->api_version[0] != DROPBEAR_PLUGIN_VERSION_MAJOR) || + (svr_ses.plugin_instance->api_version[1] < DROPBEAR_PLUGIN_VERSION_MINOR) ) { dropbear_exit("plugin version check failed: " "Dropbear=%d.%d, plugin=%d.%d", - DROPBEAR_EPKA_VERSION_MAJOR, DROPBEAR_EPKA_VERSION_MINOR, - svr_ses.epka_instance->api_version[0], svr_ses.epka_instance->api_version[1]); + DROPBEAR_PLUGIN_VERSION_MAJOR, DROPBEAR_PLUGIN_VERSION_MINOR, + svr_ses.plugin_instance->api_version[0], svr_ses.plugin_instance->api_version[1]); } - if (svr_ses.epka_instance->api_version[1] > DROPBEAR_EPKA_VERSION_MINOR) { + if (svr_ses.plugin_instance->api_version[1] > DROPBEAR_PLUGIN_VERSION_MINOR) { dropbear_log(LOG_WARNING, "plugin API newer than dropbear API: " "Dropbear=%d.%d, plugin=%d.%d", - DROPBEAR_EPKA_VERSION_MAJOR, DROPBEAR_EPKA_VERSION_MINOR, - svr_ses.epka_instance->api_version[0], svr_ses.epka_instance->api_version[1]); + DROPBEAR_PLUGIN_VERSION_MAJOR, DROPBEAR_PLUGIN_VERSION_MINOR, + svr_ses.plugin_instance->api_version[0], svr_ses.plugin_instance->api_version[1]); } dropbear_log(LOG_INFO, "successfully loaded and initialized pubkey plugin '%s'", svr_opts.pubkey_plugin); } @@ -209,11 +209,11 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) { char fullmsg[300]; int i; -#if DROPBEAR_EPKA - if ((ses.epka_session != NULL)) { - svr_ses.epka_instance->delete_session(ses.epka_session); +#if DROPBEAR_PLUGIN + if ((ses.plugin_session != NULL)) { + svr_ses.plugin_instance->delete_session(ses.plugin_session); } - ses.epka_session = NULL; + ses.plugin_session = NULL; #endif /* Render the formatted exit message */ diff --git a/sysoptions.h b/sysoptions.h index 58604f0..cfd5469 100644 --- a/sysoptions.h +++ b/sysoptions.h @@ -243,8 +243,8 @@ If you test it please contact the Dropbear author */ #error "At least one server authentication type must be enabled. DROPBEAR_SVR_PUBKEY_AUTH and DROPBEAR_SVR_PASSWORD_AUTH are recommended." #endif -#if (DROPBEAR_EPKA && !DROPBEAR_SVR_PUBKEY_AUTH) - #error "You must define DROPBEAR_SVR_PUBKEY_AUTH in order to use External Public Key Authentication (EPKA)" +#if (DROPBEAR_PLUGIN && !DROPBEAR_SVR_PUBKEY_AUTH) + #error "You must define DROPBEAR_SVR_PUBKEY_AUTH in order to use plugins" #endif #if !(DROPBEAR_AES128 || DROPBEAR_3DES || DROPBEAR_AES256 || DROPBEAR_BLOWFISH \ -- cgit v1.2.3 From 2301b6ac0ba733ea95d723630bbb610195d1527a Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Mon, 15 Jun 2020 18:22:18 +0500 Subject: Disallow leading lines before the ident for server (#102) Per RFC4253 4.2 clients must be able to process other lines of data before the version string, server behavior is not defined neither with MUST/SHOULD nor with MAY. If server process up to 50 lines too - it may cause too long hanging session with invalid/evil client that consume host resources and potentially may lead to DDoS on poor embedded boxes. Let's require first line from client to be version string and fail early if it's not - matches both RFC and real OpenSSH behavior. --- common-session.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'common-session.c') diff --git a/common-session.c b/common-session.c index fc0f9a0..7531563 100644 --- a/common-session.c +++ b/common-session.c @@ -370,8 +370,11 @@ static void read_session_identification() { int len = 0; char done = 0; int i; - /* If they send more than 50 lines, something is wrong */ - for (i = 0; i < 50; i++) { + + /* Servers may send other lines of data before sending the + * version string, client must be able to process such lines. + * If they send more than 50 lines, something is wrong */ + for (i = IS_DROPBEAR_CLIENT ? 50 : 1; i > 0; i--) { len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf)); if (len < 0 && errno != EINTR) { -- cgit v1.2.3