svr-session.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /*
  2. * Dropbear - a SSH2 server
  3. *
  4. * Copyright (c) 2002,2003 Matt Johnston
  5. * All rights reserved.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. * SOFTWARE. */
  24. #include "includes.h"
  25. #include "session.h"
  26. #include "dbutil.h"
  27. #include "packet.h"
  28. #include "algo.h"
  29. #include "buffer.h"
  30. #include "dss.h"
  31. #include "ssh.h"
  32. #include "dbrandom.h"
  33. #include "kex.h"
  34. #include "channel.h"
  35. #include "chansession.h"
  36. #include "atomicio.h"
  37. #include "tcpfwd.h"
  38. #include "service.h"
  39. #include "auth.h"
  40. #include "runopts.h"
  41. #include "crypto_desc.h"
  42. #include "fuzz.h"
  43. static void svr_remoteclosed(void);
  44. static void svr_algos_initialise(void);
  45. struct serversession svr_ses; /* GLOBAL */
  46. static const packettype svr_packettypes[] = {
  47. {SSH_MSG_CHANNEL_DATA, recv_msg_channel_data},
  48. {SSH_MSG_CHANNEL_WINDOW_ADJUST, recv_msg_channel_window_adjust},
  49. {SSH_MSG_USERAUTH_REQUEST, recv_msg_userauth_request}, /* server */
  50. {SSH_MSG_SERVICE_REQUEST, recv_msg_service_request}, /* server */
  51. {SSH_MSG_KEXINIT, recv_msg_kexinit},
  52. {SSH_MSG_KEXDH_INIT, recv_msg_kexdh_init}, /* server */
  53. {SSH_MSG_NEWKEYS, recv_msg_newkeys},
  54. {SSH_MSG_GLOBAL_REQUEST, recv_msg_global_request_remotetcp},
  55. {SSH_MSG_CHANNEL_REQUEST, recv_msg_channel_request},
  56. {SSH_MSG_CHANNEL_OPEN, recv_msg_channel_open},
  57. {SSH_MSG_CHANNEL_EOF, recv_msg_channel_eof},
  58. {SSH_MSG_CHANNEL_CLOSE, recv_msg_channel_close},
  59. {SSH_MSG_CHANNEL_SUCCESS, ignore_recv_response},
  60. {SSH_MSG_CHANNEL_FAILURE, ignore_recv_response},
  61. {SSH_MSG_REQUEST_FAILURE, ignore_recv_response}, /* for keepalive */
  62. {SSH_MSG_REQUEST_SUCCESS, ignore_recv_response}, /* client */
  63. #if DROPBEAR_LISTENERS
  64. {SSH_MSG_CHANNEL_OPEN_CONFIRMATION, recv_msg_channel_open_confirmation},
  65. {SSH_MSG_CHANNEL_OPEN_FAILURE, recv_msg_channel_open_failure},
  66. #endif
  67. {0, NULL} /* End */
  68. };
  69. static const struct ChanType *svr_chantypes[] = {
  70. &svrchansess,
  71. #if DROPBEAR_SVR_LOCALTCPFWD
  72. &svr_chan_tcpdirect,
  73. #endif
  74. NULL /* Null termination is mandatory. */
  75. };
  76. static void
  77. svr_session_cleanup(void) {
  78. /* free potential public key options */
  79. svr_pubkey_options_cleanup();
  80. m_free(svr_ses.addrstring);
  81. m_free(svr_ses.remotehost);
  82. m_free(svr_ses.childpids);
  83. svr_ses.childpidsize = 0;
  84. #if DROPBEAR_PLUGIN
  85. if (svr_ses.plugin_handle != NULL) {
  86. if (svr_ses.plugin_instance) {
  87. svr_ses.plugin_instance->delete_plugin(svr_ses.plugin_instance);
  88. svr_ses.plugin_instance = NULL;
  89. }
  90. dlclose(svr_ses.plugin_handle);
  91. svr_ses.plugin_handle = NULL;
  92. }
  93. #endif
  94. }
  95. void svr_session(int sock, int childpipe) {
  96. char *host, *port;
  97. size_t len;
  98. common_session_init(sock, sock);
  99. /* Initialise server specific parts of the session */
  100. svr_ses.childpipe = childpipe;
  101. #if DROPBEAR_VFORK
  102. svr_ses.server_pid = getpid();
  103. #endif
  104. /* for logging the remote address */
  105. get_socket_address(ses.sock_in, NULL, NULL, &host, &port, 0);
  106. len = strlen(host) + strlen(port) + 2;
  107. svr_ses.addrstring = m_malloc(len);
  108. snprintf(svr_ses.addrstring, len, "%s:%s", host, port);
  109. m_free(host);
  110. m_free(port);
  111. #if DROPBEAR_PLUGIN
  112. /* Initializes the PLUGIN Plugin */
  113. svr_ses.plugin_handle = NULL;
  114. svr_ses.plugin_instance = NULL;
  115. if (svr_opts.pubkey_plugin) {
  116. #if DEBUG_TRACE
  117. const int verbose = debug_trace;
  118. #else
  119. const int verbose = 0;
  120. #endif
  121. PubkeyExtPlugin_newFn pluginConstructor;
  122. /* RTLD_NOW: fails if not all the symbols are resolved now. Better fail now than at run-time */
  123. svr_ses.plugin_handle = dlopen(svr_opts.pubkey_plugin, RTLD_NOW);
  124. if (svr_ses.plugin_handle == NULL) {
  125. dropbear_exit("failed to load external pubkey plugin '%s': %s", svr_opts.pubkey_plugin, dlerror());
  126. }
  127. pluginConstructor = (PubkeyExtPlugin_newFn)dlsym(svr_ses.plugin_handle, DROPBEAR_PUBKEY_PLUGIN_FNNAME_NEW);
  128. if (!pluginConstructor) {
  129. dropbear_exit("plugin constructor method not found in external pubkey plugin");
  130. }
  131. /* Create an instance of the plugin */
  132. svr_ses.plugin_instance = pluginConstructor(verbose, svr_opts.pubkey_plugin_options, svr_ses.addrstring);
  133. if (svr_ses.plugin_instance == NULL) {
  134. dropbear_exit("external plugin initialization failed");
  135. }
  136. /* Check if the plugin is compatible */
  137. if ( (svr_ses.plugin_instance->api_version[0] != DROPBEAR_PLUGIN_VERSION_MAJOR) ||
  138. (svr_ses.plugin_instance->api_version[1] < DROPBEAR_PLUGIN_VERSION_MINOR) ) {
  139. dropbear_exit("plugin version check failed: "
  140. "Dropbear=%d.%d, plugin=%d.%d",
  141. DROPBEAR_PLUGIN_VERSION_MAJOR, DROPBEAR_PLUGIN_VERSION_MINOR,
  142. svr_ses.plugin_instance->api_version[0], svr_ses.plugin_instance->api_version[1]);
  143. }
  144. if (svr_ses.plugin_instance->api_version[1] > DROPBEAR_PLUGIN_VERSION_MINOR) {
  145. dropbear_log(LOG_WARNING, "plugin API newer than dropbear API: "
  146. "Dropbear=%d.%d, plugin=%d.%d",
  147. DROPBEAR_PLUGIN_VERSION_MAJOR, DROPBEAR_PLUGIN_VERSION_MINOR,
  148. svr_ses.plugin_instance->api_version[0], svr_ses.plugin_instance->api_version[1]);
  149. }
  150. dropbear_log(LOG_INFO, "successfully loaded and initialized pubkey plugin '%s'", svr_opts.pubkey_plugin);
  151. }
  152. #endif
  153. svr_authinitialise();
  154. chaninitialise(svr_chantypes);
  155. svr_chansessinitialise();
  156. svr_algos_initialise();
  157. get_socket_address(ses.sock_in, NULL, NULL,
  158. &svr_ses.remotehost, NULL, 1);
  159. /* set up messages etc */
  160. ses.remoteclosed = svr_remoteclosed;
  161. ses.extra_session_cleanup = svr_session_cleanup;
  162. /* packet handlers */
  163. ses.packettypes = svr_packettypes;
  164. ses.isserver = 1;
  165. /* We're ready to go now */
  166. ses.init_done = 1;
  167. /* exchange identification, version etc */
  168. send_session_identification();
  169. kexfirstinitialise(); /* initialise the kex state */
  170. /* start off with key exchange */
  171. send_msg_kexinit();
  172. #if DROPBEAR_FUZZ
  173. if (fuzz.fuzzing) {
  174. fuzz_svr_hook_preloop();
  175. }
  176. #endif
  177. /* Run the main for-loop. */
  178. session_loop(svr_chansess_checksignal);
  179. /* Not reached */
  180. }
  181. /* failure exit - format must be <= 100 chars */
  182. void svr_dropbear_exit(int exitcode, const char* format, va_list param) {
  183. char exitmsg[150];
  184. char fullmsg[300];
  185. char fromaddr[60];
  186. int i;
  187. int add_delay = 0;
  188. #if DROPBEAR_PLUGIN
  189. if ((ses.plugin_session != NULL)) {
  190. svr_ses.plugin_instance->delete_session(ses.plugin_session);
  191. }
  192. ses.plugin_session = NULL;
  193. #endif
  194. /* Render the formatted exit message */
  195. vsnprintf(exitmsg, sizeof(exitmsg), format, param);
  196. /* svr_ses.addrstring may not be set for some early exits, or for
  197. the listener process */
  198. fromaddr[0] = '\0';
  199. if (svr_ses.addrstring) {
  200. snprintf(fromaddr, sizeof(fromaddr), " from <%s>", svr_ses.addrstring);
  201. }
  202. /* Add the prefix depending on session/auth state */
  203. if (!ses.init_done) {
  204. /* before session init */
  205. snprintf(fullmsg, sizeof(fullmsg), "Early exit%s: %s", fromaddr, exitmsg);
  206. } else if (ses.authstate.authdone) {
  207. /* user has authenticated */
  208. snprintf(fullmsg, sizeof(fullmsg),
  209. "Exit (%s)%s: %s",
  210. ses.authstate.pw_name, fromaddr, exitmsg);
  211. } else if (ses.authstate.pw_name) {
  212. /* we have a potential user */
  213. snprintf(fullmsg, sizeof(fullmsg),
  214. "Exit before auth%s: (user '%s', %u fails): %s",
  215. fromaddr, ses.authstate.pw_name, ses.authstate.failcount, exitmsg);
  216. add_delay = 1;
  217. } else {
  218. /* before userauth */
  219. snprintf(fullmsg, sizeof(fullmsg), "Exit before auth%s: %s", fromaddr, exitmsg);
  220. add_delay = 1;
  221. }
  222. dropbear_log(LOG_INFO, "%s", fullmsg);
  223. /* To make it harder for attackers, introduce a delay to keep an
  224. * unauthenticated session open a bit longer, thus blocking a connection
  225. * slot until after the delay. Without this, while there is a limit on
  226. * the amount of attempts an attacker can make at the same time
  227. * (MAX_UNAUTH_PER_IP), the time taken by dropbear to handle one attempt
  228. * is still short and thus for each of the allowed parallel attempts
  229. * many attempts can be chained one after the other. The attempt rate is
  230. * then:
  231. * "MAX_UNAUTH_PER_IP / <process time of one attempt>".
  232. * With the delay, this rate becomes:
  233. * "MAX_UNAUTH_PER_IP / UNAUTH_CLOSE_DELAY".
  234. */
  235. if ((add_delay != 0) && (UNAUTH_CLOSE_DELAY > 0)) {
  236. TRACE(("svr_dropbear_exit: start delay of %d seconds", UNAUTH_CLOSE_DELAY));
  237. sleep(UNAUTH_CLOSE_DELAY);
  238. TRACE(("svr_dropbear_exit: end delay of %d seconds", UNAUTH_CLOSE_DELAY));
  239. }
  240. #if DROPBEAR_VFORK
  241. /* For uclinux only the main server process should cleanup - we don't want
  242. * forked children doing that */
  243. if (svr_ses.server_pid == getpid())
  244. #endif
  245. {
  246. /* must be after we've done with username etc */
  247. session_cleanup();
  248. }
  249. #if DROPBEAR_FUZZ
  250. /* longjmp before cleaning up svr_opts */
  251. if (fuzz.do_jmp) {
  252. longjmp(fuzz.jmp, 1);
  253. }
  254. #endif
  255. if (svr_opts.hostkey) {
  256. sign_key_free(svr_opts.hostkey);
  257. svr_opts.hostkey = NULL;
  258. }
  259. for (i = 0; i < DROPBEAR_MAX_PORTS; i++) {
  260. m_free(svr_opts.addresses[i]);
  261. m_free(svr_opts.ports[i]);
  262. }
  263. exit(exitcode);
  264. }
  265. /* priority is priority as with syslog() */
  266. void svr_dropbear_log(int priority, const char* format, va_list param) {
  267. char printbuf[1024];
  268. char datestr[20];
  269. time_t timesec;
  270. int havetrace = 0;
  271. vsnprintf(printbuf, sizeof(printbuf), format, param);
  272. #ifndef DISABLE_SYSLOG
  273. if (opts.usingsyslog) {
  274. syslog(priority, "%s", printbuf);
  275. }
  276. #endif
  277. /* if we are using DEBUG_TRACE, we want to print to stderr even if
  278. * syslog is used, so it is included in error reports */
  279. #if DEBUG_TRACE
  280. havetrace = debug_trace;
  281. #endif
  282. if (!opts.usingsyslog || havetrace) {
  283. struct tm * local_tm = NULL;
  284. timesec = time(NULL);
  285. local_tm = localtime(&timesec);
  286. if (local_tm == NULL
  287. || strftime(datestr, sizeof(datestr), "%b %d %H:%M:%S",
  288. local_tm) == 0)
  289. {
  290. /* upon failure, just print the epoch-seconds time. */
  291. snprintf(datestr, sizeof(datestr), "%d", (int)timesec);
  292. }
  293. fprintf(stderr, "[%d] %s %s\n", getpid(), datestr, printbuf);
  294. }
  295. }
  296. /* called when the remote side closes the connection */
  297. static void svr_remoteclosed() {
  298. m_close(ses.sock_in);
  299. if (ses.sock_in != ses.sock_out) {
  300. m_close(ses.sock_out);
  301. }
  302. ses.sock_in = -1;
  303. ses.sock_out = -1;
  304. dropbear_close("Exited normally");
  305. }
  306. static void svr_algos_initialise(void) {
  307. algo_type *algo;
  308. for (algo = sshkex; algo->name; algo++) {
  309. #if DROPBEAR_DH_GROUP1 && DROPBEAR_DH_GROUP1_CLIENTONLY
  310. if (strcmp(algo->name, "diffie-hellman-group1-sha1") == 0) {
  311. algo->usable = 0;
  312. }
  313. #endif
  314. #if DROPBEAR_EXT_INFO
  315. if (strcmp(algo->name, SSH_EXT_INFO_C) == 0) {
  316. algo->usable = 0;
  317. }
  318. #endif
  319. }
  320. }