Home | History | Annotate | Download | only in dropbear
      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 
     33 static size_t listensockets(int *sock, size_t sockcount, int *maxfd);
     34 static void sigchld_handler(int dummy);
     35 static void sigsegv_handler(int);
     36 static void sigintterm_handler(int fish);
     37 #ifdef INETD_MODE
     38 static void main_inetd();
     39 #endif
     40 #ifdef NON_INETD_MODE
     41 static void main_noinetd();
     42 #endif
     43 static void commonsetup();
     44 
     45 #if defined(DBMULTI_dropbear) || !defined(DROPBEAR_MULTI)
     46 #if defined(DBMULTI_dropbear) && defined(DROPBEAR_MULTI)
     47 int dropbear_main(int argc, char ** argv)
     48 #else
     49 int 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
     79 static 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
    112 void 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 
    318 out:
    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 */
    333 static 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 */
    346 static 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 */
    353 static void sigintterm_handler(int UNUSED(unused)) {
    354 
    355 	exitflag = 1;
    356 }
    357 
    358 /* Things used by inetd and non-inetd modes */
    359 static 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 */
    395 static 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