1/* 2 * Dropbear - a SSH2 server 3 * 4 * Copyright (c) 2002-2006 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 25#include "includes.h" 26#include "dbutil.h" 27#include "session.h" 28#include "buffer.h" 29#include "signkey.h" 30#include "runopts.h" 31#include "random.h" 32 33static size_t listensockets(int *sock, size_t sockcount, int *maxfd); 34static void sigchld_handler(int dummy); 35static void sigsegv_handler(int); 36static void sigintterm_handler(int fish); 37#ifdef INETD_MODE 38static void main_inetd(); 39#endif 40#ifdef NON_INETD_MODE 41static void main_noinetd(); 42#endif 43static void commonsetup(); 44 45#if defined(DBMULTI_dropbear) || !defined(DROPBEAR_MULTI) 46#if defined(DBMULTI_dropbear) && defined(DROPBEAR_MULTI) 47int dropbear_main(int argc, char ** argv) 48#else 49int main(int argc, char ** argv) 50#endif 51{ 52 _dropbear_exit = svr_dropbear_exit; 53 _dropbear_log = svr_dropbear_log; 54 55 disallow_core(); 56 57 /* get commandline options */ 58 svr_getopts(argc, argv); 59 60#ifdef INETD_MODE 61 /* service program mode */ 62 if (svr_opts.inetdmode) { 63 main_inetd(); 64 /* notreached */ 65 } 66#endif 67 68#ifdef NON_INETD_MODE 69 main_noinetd(); 70 /* notreached */ 71#endif 72 73 dropbear_exit("Compiled without normal mode, can't run without -i\n"); 74 return -1; 75} 76#endif 77 78#ifdef INETD_MODE 79static void main_inetd() { 80 81 struct sockaddr_storage remoteaddr; 82 socklen_t remoteaddrlen; 83 char * addrstring = NULL; 84 85 /* Set up handlers, syslog, seed random */ 86 commonsetup(); 87 88 remoteaddrlen = sizeof(remoteaddr); 89 if (getpeername(0, (struct sockaddr*)&remoteaddr, &remoteaddrlen) < 0) { 90 dropbear_exit("Unable to getpeername: %s", strerror(errno)); 91 } 92 93 /* In case our inetd was lax in logging source addresses */ 94 addrstring = getaddrstring(&remoteaddr, 1); 95 dropbear_log(LOG_INFO, "Child connection from %s", addrstring); 96 97 /* Don't check the return value - it may just fail since inetd has 98 * already done setsid() after forking (xinetd on Darwin appears to do 99 * this */ 100 setsid(); 101 102 /* Start service program 103 * -1 is a dummy childpipe, just something we can close() without 104 * mattering. */ 105 svr_session(0, -1, getaddrhostname(&remoteaddr), addrstring); 106 107 /* notreached */ 108} 109#endif /* INETD_MODE */ 110 111#ifdef NON_INETD_MODE 112void main_noinetd() { 113 fd_set fds; 114 struct timeval seltimeout; 115 unsigned int i, j; 116 int val; 117 int maxsock = -1; 118 int listensocks[MAX_LISTEN_ADDR]; 119 size_t listensockcount = 0; 120 FILE *pidfile = NULL; 121 122 int childpipes[MAX_UNAUTH_CLIENTS]; 123 char * preauth_addrs[MAX_UNAUTH_CLIENTS]; 124 125 int childsock; 126 int childpipe[2]; 127 128 /* Note: commonsetup() must happen before we daemon()ise. Otherwise 129 daemon() will chdir("/"), and we won't be able to find local-dir 130 hostkeys. */ 131 commonsetup(); 132 133 /* fork */ 134 if (svr_opts.forkbg) { 135 int closefds = 0; 136#ifndef DEBUG_TRACE 137 if (!svr_opts.usingsyslog) { 138 closefds = 1; 139 } 140#endif 141 if (daemon(0, closefds) < 0) { 142 dropbear_exit("Failed to daemonize: %s", strerror(errno)); 143 } 144 } 145 146 /* should be done after syslog is working */ 147 if (svr_opts.forkbg) { 148 dropbear_log(LOG_INFO, "Running in background"); 149 } else { 150 dropbear_log(LOG_INFO, "Not forking"); 151 } 152 153 /* create a PID file so that we can be killed easily */ 154 pidfile = fopen(svr_opts.pidfile, "w"); 155 if (pidfile) { 156 fprintf(pidfile, "%d\n", getpid()); 157 fclose(pidfile); 158 } 159 160 /* sockets to identify pre-authenticated clients */ 161 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) { 162 childpipes[i] = -1; 163 } 164 bzero(preauth_addrs, sizeof(preauth_addrs)); 165 166 /* Set up the listening sockets */ 167 listensockcount = listensockets(listensocks, MAX_LISTEN_ADDR, &maxsock); 168 if (listensockcount == 0) 169 { 170 dropbear_exit("No listening ports available."); 171 } 172 173 /* incoming connection select loop */ 174 for(;;) { 175 176 FD_ZERO(&fds); 177 178 seltimeout.tv_sec = 60; 179 seltimeout.tv_usec = 0; 180 181 /* listening sockets */ 182 for (i = 0; i < listensockcount; i++) { 183 FD_SET(listensocks[i], &fds); 184 } 185 186 /* pre-authentication clients */ 187 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) { 188 if (childpipes[i] >= 0) { 189 FD_SET(childpipes[i], &fds); 190 maxsock = MAX(maxsock, childpipes[i]); 191 } 192 } 193 194 val = select(maxsock+1, &fds, NULL, NULL, &seltimeout); 195 196 if (exitflag) { 197 unlink(svr_opts.pidfile); 198 dropbear_exit("Terminated by signal"); 199 } 200 201 if (val == 0) { 202 /* timeout reached */ 203 continue; 204 } 205 206 if (val < 0) { 207 if (errno == EINTR) { 208 continue; 209 } 210 dropbear_exit("Listening socket error"); 211 } 212 213 /* close fds which have been authed or closed - svr-auth.c handles 214 * closing the auth sockets on success */ 215 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) { 216 if (childpipes[i] >= 0 && FD_ISSET(childpipes[i], &fds)) { 217 m_close(childpipes[i]); 218 childpipes[i] = -1; 219 m_free(preauth_addrs[i]); 220 } 221 } 222 223 /* handle each socket which has something to say */ 224 for (i = 0; i < listensockcount; i++) { 225 226 struct sockaddr_storage remoteaddr; 227 socklen_t remoteaddrlen = 0; 228 size_t num_unauthed_for_addr = 0; 229 size_t num_unauthed_total = 0; 230 char * remote_addr_str = NULL; 231 pid_t fork_ret = 0; 232 size_t conn_idx = 0; 233 234 if (!FD_ISSET(listensocks[i], &fds)) 235 continue; 236 237 remoteaddrlen = sizeof(remoteaddr); 238 childsock = accept(listensocks[i], 239 (struct sockaddr*)&remoteaddr, &remoteaddrlen); 240 241 if (childsock < 0) { 242 /* accept failed */ 243 continue; 244 } 245 246 /* Limit the number of unauthenticated connections per IP */ 247 remote_addr_str = getaddrstring(&remoteaddr, 0); 248 249 num_unauthed_for_addr = 0; 250 num_unauthed_total = 0; 251 for (j = 0; j < MAX_UNAUTH_CLIENTS; j++) { 252 if (childpipes[j] >= 0) { 253 num_unauthed_total++; 254 if (strcmp(remote_addr_str, preauth_addrs[j]) == 0) { 255 num_unauthed_for_addr++; 256 } 257 } else { 258 /* a free slot */ 259 conn_idx = j; 260 } 261 } 262 263 if (num_unauthed_total >= MAX_UNAUTH_CLIENTS 264 || num_unauthed_for_addr >= MAX_UNAUTH_PER_IP) { 265 goto out; 266 } 267 268 if (pipe(childpipe) < 0) { 269 TRACE(("error creating child pipe")) 270 goto out; 271 } 272 273 fork_ret = fork(); 274 if (fork_ret < 0) { 275 dropbear_log(LOG_WARNING, "error forking: %s", strerror(errno)); 276 goto out; 277 278 } else if (fork_ret > 0) { 279 280 /* parent */ 281 childpipes[conn_idx] = childpipe[0]; 282 m_close(childpipe[1]); 283 preauth_addrs[conn_idx] = remote_addr_str; 284 remote_addr_str = NULL; 285 286 } else { 287 288 /* child */ 289 char * addrstring = NULL; 290#ifdef DEBUG_FORKGPROF 291 extern void _start(void), etext(void); 292 monstartup((u_long)&_start, (u_long)&etext); 293#endif /* DEBUG_FORKGPROF */ 294 295 m_free(remote_addr_str); 296 addrstring = getaddrstring(&remoteaddr, 1); 297 dropbear_log(LOG_INFO, "Child connection from %s", addrstring); 298 299 if (setsid() < 0) { 300 dropbear_exit("setsid: %s", strerror(errno)); 301 } 302 303 /* make sure we close sockets */ 304 for (i = 0; i < listensockcount; i++) { 305 m_close(listensocks[i]); 306 } 307 308 m_close(childpipe[0]); 309 310 /* start the session */ 311 svr_session(childsock, childpipe[1], 312 getaddrhostname(&remoteaddr), 313 addrstring); 314 /* don't return */ 315 dropbear_assert(0); 316 } 317 318out: 319 /* This section is important for the parent too */ 320 m_close(childsock); 321 if (remote_addr_str) { 322 m_free(remote_addr_str); 323 } 324 } 325 } /* for(;;) loop */ 326 327 /* don't reach here */ 328} 329#endif /* NON_INETD_MODE */ 330 331 332/* catch + reap zombie children */ 333static void sigchld_handler(int UNUSED(unused)) { 334 struct sigaction sa_chld; 335 336 while(waitpid(-1, NULL, WNOHANG) > 0); 337 338 sa_chld.sa_handler = sigchld_handler; 339 sa_chld.sa_flags = SA_NOCLDSTOP; 340 if (sigaction(SIGCHLD, &sa_chld, NULL) < 0) { 341 dropbear_exit("signal() error"); 342 } 343} 344 345/* catch any segvs */ 346static void sigsegv_handler(int UNUSED(unused)) { 347 fprintf(stderr, "Aiee, segfault! You should probably report " 348 "this as a bug to the developer\n"); 349 exit(EXIT_FAILURE); 350} 351 352/* catch ctrl-c or sigterm */ 353static void sigintterm_handler(int UNUSED(unused)) { 354 355 exitflag = 1; 356} 357 358/* Things used by inetd and non-inetd modes */ 359static void commonsetup() { 360 361 struct sigaction sa_chld; 362#ifndef DISABLE_SYSLOG 363 if (svr_opts.usingsyslog) { 364 startsyslog(); 365 } 366#endif 367 368 /* set up cleanup handler */ 369 if (signal(SIGINT, sigintterm_handler) == SIG_ERR || 370#ifndef DEBUG_VALGRIND 371 signal(SIGTERM, sigintterm_handler) == SIG_ERR || 372#endif 373 signal(SIGPIPE, SIG_IGN) == SIG_ERR) { 374 dropbear_exit("signal() error"); 375 } 376 377 /* catch and reap zombie children */ 378 sa_chld.sa_handler = sigchld_handler; 379 sa_chld.sa_flags = SA_NOCLDSTOP; 380 if (sigaction(SIGCHLD, &sa_chld, NULL) < 0) { 381 dropbear_exit("signal() error"); 382 } 383 if (signal(SIGSEGV, sigsegv_handler) == SIG_ERR) { 384 dropbear_exit("signal() error"); 385 } 386 387 /* Now we can setup the hostkeys - needs to be after logging is on, 388 * otherwise we might end up blatting error messages to the socket */ 389 loadhostkeys(); 390 391 seedrandom(); 392} 393 394/* Set up listening sockets for all the requested ports */ 395static size_t listensockets(int *sock, size_t sockcount, int *maxfd) { 396 397 unsigned int i; 398 char* errstring = NULL; 399 size_t sockpos = 0; 400 int nsock; 401 402 TRACE(("listensockets: %d to try\n", svr_opts.portcount)) 403 404 for (i = 0; i < svr_opts.portcount; i++) { 405 406 TRACE(("listening on '%s:%s'", svr_opts.addresses[i], svr_opts.ports[i])) 407 408 nsock = dropbear_listen(svr_opts.addresses[i], svr_opts.ports[i], &sock[sockpos], 409 sockcount - sockpos, 410 &errstring, maxfd); 411 412 if (nsock < 0) { 413 dropbear_log(LOG_WARNING, "Failed listening on '%s': %s", 414 svr_opts.ports[i], errstring); 415 m_free(errstring); 416 continue; 417 } 418 419 sockpos += nsock; 420 421 } 422 return sockpos; 423} 424