comparison svr-main.c @ 297:79bf1023cf11 agent-client

propagate from branch 'au.asn.ucc.matt.dropbear' (head 0501e6f661b5415eb76f3b312d183c3adfbfb712) to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head 01038174ec27245b51bd43a66c01ad930880f67b)
author Matt Johnston <matt@ucc.asn.au>
date Tue, 21 Mar 2006 16:20:59 +0000
parents 94ee16f5b8a8
children 9d110777f345 7dad470ad4aa 0aaaf68e97dc
comparison
equal deleted inserted replaced
225:ca7e76d981d9 297:79bf1023cf11
1 /* 1 /*
2 * Dropbear - a SSH2 server 2 * Dropbear - a SSH2 server
3 * 3 *
4 * Copyright (c) 2002,2003 Matt Johnston 4 * Copyright (c) 2002-2006 Matt Johnston
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy 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 8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights 9 * in the Software without restriction, including without limitation the rights
27 #include "session.h" 27 #include "session.h"
28 #include "buffer.h" 28 #include "buffer.h"
29 #include "signkey.h" 29 #include "signkey.h"
30 #include "runopts.h" 30 #include "runopts.h"
31 31
32 static int listensockets(int *sock, int sockcount, int *maxfd); 32 static size_t listensockets(int *sock, size_t sockcount, int *maxfd);
33 static void sigchld_handler(int dummy); 33 static void sigchld_handler(int dummy);
34 static void sigsegv_handler(int); 34 static void sigsegv_handler(int);
35 static void sigintterm_handler(int fish); 35 static void sigintterm_handler(int fish);
36 #ifdef INETD_MODE 36 #ifdef INETD_MODE
37 static void main_inetd(); 37 static void main_inetd();
39 #ifdef NON_INETD_MODE 39 #ifdef NON_INETD_MODE
40 static void main_noinetd(); 40 static void main_noinetd();
41 #endif 41 #endif
42 static void commonsetup(); 42 static void commonsetup();
43 43
44 static int childpipes[MAX_UNAUTH_CLIENTS];
45
46 #if defined(DBMULTI_dropbear) || !defined(DROPBEAR_MULTI) 44 #if defined(DBMULTI_dropbear) || !defined(DROPBEAR_MULTI)
47 #if defined(DBMULTI_dropbear) && defined(DROPBEAR_MULTI) 45 #if defined(DBMULTI_dropbear) && defined(DROPBEAR_MULTI)
48 int dropbear_main(int argc, char ** argv) 46 int dropbear_main(int argc, char ** argv)
49 #else 47 #else
50 int main(int argc, char ** argv) 48 int main(int argc, char ** argv)
51 #endif 49 #endif
52 { 50 {
53
54
55 _dropbear_exit = svr_dropbear_exit; 51 _dropbear_exit = svr_dropbear_exit;
56 _dropbear_log = svr_dropbear_log; 52 _dropbear_log = svr_dropbear_log;
57 53
58 /* get commandline options */ 54 /* get commandline options */
59 svr_getopts(argc, argv); 55 svr_getopts(argc, argv);
78 74
79 #ifdef INETD_MODE 75 #ifdef INETD_MODE
80 static void main_inetd() { 76 static void main_inetd() {
81 77
82 struct sockaddr_storage remoteaddr; 78 struct sockaddr_storage remoteaddr;
83 int remoteaddrlen; 79 socklen_t remoteaddrlen;
84 char * addrstring = NULL; 80 char * addrstring = NULL;
85 81
86 /* Set up handlers, syslog */ 82 /* Set up handlers, syslog, seed random */
87 commonsetup(); 83 commonsetup();
88 84
89 remoteaddrlen = sizeof(remoteaddr); 85 remoteaddrlen = sizeof(remoteaddr);
90 if (getpeername(0, (struct sockaddr*)&remoteaddr, &remoteaddrlen) < 0) { 86 if (getpeername(0, (struct sockaddr*)&remoteaddr, &remoteaddrlen) < 0) {
91 dropbear_exit("Unable to getpeername: %s", strerror(errno)); 87 dropbear_exit("Unable to getpeername: %s", strerror(errno));
114 fd_set fds; 110 fd_set fds;
115 struct timeval seltimeout; 111 struct timeval seltimeout;
116 unsigned int i, j; 112 unsigned int i, j;
117 int val; 113 int val;
118 int maxsock = -1; 114 int maxsock = -1;
119 struct sockaddr_storage remoteaddr;
120 int remoteaddrlen;
121 int listensocks[MAX_LISTEN_ADDR]; 115 int listensocks[MAX_LISTEN_ADDR];
122 int listensockcount = 0; 116 size_t listensockcount = 0;
123 FILE *pidfile = NULL; 117 FILE *pidfile = NULL;
124 118
119 int childpipes[MAX_UNAUTH_CLIENTS];
120 char * preauth_addrs[MAX_UNAUTH_CLIENTS];
121
125 int childsock; 122 int childsock;
126 pid_t childpid;
127 int childpipe[2]; 123 int childpipe[2];
128 124
129 /* fork */ 125 /* fork */
130 if (svr_opts.forkbg) { 126 if (svr_opts.forkbg) {
131 int closefds = 0; 127 int closefds = 0;
139 } 135 }
140 } 136 }
141 137
142 commonsetup(); 138 commonsetup();
143 139
144
145 /* should be done after syslog is working */ 140 /* should be done after syslog is working */
146 if (svr_opts.forkbg) { 141 if (svr_opts.forkbg) {
147 dropbear_log(LOG_INFO, "Running in background"); 142 dropbear_log(LOG_INFO, "Running in background");
148 } else { 143 } else {
149 dropbear_log(LOG_INFO, "Not forking"); 144 dropbear_log(LOG_INFO, "Not forking");
158 153
159 /* sockets to identify pre-authenticated clients */ 154 /* sockets to identify pre-authenticated clients */
160 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) { 155 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) {
161 childpipes[i] = -1; 156 childpipes[i] = -1;
162 } 157 }
158 bzero(preauth_addrs, sizeof(preauth_addrs));
163 159
164 /* Set up the listening sockets */ 160 /* Set up the listening sockets */
165 /* XXX XXX ports */
166 listensockcount = listensockets(listensocks, MAX_LISTEN_ADDR, &maxsock); 161 listensockcount = listensockets(listensocks, MAX_LISTEN_ADDR, &maxsock);
167 if (listensockcount < 0) { 162 if (listensockcount == 0)
163 {
168 dropbear_exit("No listening ports available."); 164 dropbear_exit("No listening ports available.");
169 } 165 }
170 166
171 /* incoming connection select loop */ 167 /* incoming connection select loop */
172 for(;;) { 168 for(;;) {
175 171
176 seltimeout.tv_sec = 60; 172 seltimeout.tv_sec = 60;
177 seltimeout.tv_usec = 0; 173 seltimeout.tv_usec = 0;
178 174
179 /* listening sockets */ 175 /* listening sockets */
180 for (i = 0; i < (unsigned int)listensockcount; i++) { 176 for (i = 0; i < listensockcount; i++) {
181 FD_SET(listensocks[i], &fds); 177 FD_SET(listensocks[i], &fds);
182 } 178 }
183 179
184 /* pre-authentication clients */ 180 /* pre-authentication clients */
185 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) { 181 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) {
206 continue; 202 continue;
207 } 203 }
208 dropbear_exit("Listening socket error"); 204 dropbear_exit("Listening socket error");
209 } 205 }
210 206
211 /* close fds which have been authed or closed - auth.c handles 207 /* close fds which have been authed or closed - svr-auth.c handles
212 * closing the auth sockets on success */ 208 * closing the auth sockets on success */
213 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) { 209 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) {
214 if (childpipes[i] >= 0 && FD_ISSET(childpipes[i], &fds)) { 210 if (childpipes[i] >= 0 && FD_ISSET(childpipes[i], &fds)) {
215 close(childpipes[i]); 211 m_close(childpipes[i]);
216 childpipes[i] = -1; 212 childpipes[i] = -1;
213 m_free(preauth_addrs[i]);
217 } 214 }
218 } 215 }
219 216
220 /* handle each socket which has something to say */ 217 /* handle each socket which has something to say */
221 for (i = 0; i < (unsigned int)listensockcount; i++) { 218 for (i = 0; i < listensockcount; i++) {
219
220 struct sockaddr_storage remoteaddr;
221 socklen_t remoteaddrlen = 0;
222 size_t num_unauthed_for_addr = 0;
223 size_t num_unauthed_total = 0;
224 char * remote_addr_str = NULL;
225 pid_t fork_ret = 0;
226 size_t conn_idx = 0;
227
222 if (!FD_ISSET(listensocks[i], &fds)) 228 if (!FD_ISSET(listensocks[i], &fds))
223 continue; 229 continue;
224 230
225 remoteaddrlen = sizeof(remoteaddr); 231 remoteaddrlen = sizeof(remoteaddr);
226 childsock = accept(listensocks[i], 232 childsock = accept(listensocks[i],
229 if (childsock < 0) { 235 if (childsock < 0) {
230 /* accept failed */ 236 /* accept failed */
231 continue; 237 continue;
232 } 238 }
233 239
234 /* check for max number of connections not authorised */ 240 /* Limit the number of unauthenticated connections per IP */
241 remote_addr_str = getaddrstring(&remoteaddr, 0);
242
243 num_unauthed_for_addr = 0;
244 num_unauthed_total = 0;
235 for (j = 0; j < MAX_UNAUTH_CLIENTS; j++) { 245 for (j = 0; j < MAX_UNAUTH_CLIENTS; j++) {
236 if (childpipes[j] < 0) { 246 if (childpipes[j] >= 0) {
237 break; 247 num_unauthed_total++;
248 if (strcmp(remote_addr_str, preauth_addrs[j]) == 0) {
249 num_unauthed_for_addr++;
250 }
251 } else {
252 /* a free slot */
253 conn_idx = j;
238 } 254 }
239 } 255 }
240 256
241 if (j == MAX_UNAUTH_CLIENTS) { 257 if (num_unauthed_total >= MAX_UNAUTH_CLIENTS
242 /* no free connections */ 258 || num_unauthed_for_addr >= MAX_UNAUTH_PER_IP) {
243 /* TODO - possibly log, though this would be an easy way 259 goto out;
244 * to fill logs/disk */
245 close(childsock);
246 continue;
247 } 260 }
248 261
249 if (pipe(childpipe) < 0) { 262 if (pipe(childpipe) < 0) {
250 TRACE(("error creating child pipe")) 263 TRACE(("error creating child pipe"))
251 close(childsock); 264 goto out;
252 continue; 265 }
253 } 266
254 267 fork_ret = fork();
255 if ((childpid = fork()) == 0) { 268 if (fork_ret < 0) {
269 dropbear_log(LOG_WARNING, "error forking: %s", strerror(errno));
270 goto out;
271
272 } else if (fork_ret > 0) {
273
274 /* parent */
275 childpipes[conn_idx] = childpipe[0];
276 m_close(childpipe[1]);
277 preauth_addrs[conn_idx] = remote_addr_str;
278 remote_addr_str = NULL;
279
280 } else {
256 281
257 /* child */ 282 /* child */
258 char * addrstring = NULL; 283 char * addrstring = NULL;
259 #ifdef DEBUG_FORKGPROF 284 #ifdef DEBUG_FORKGPROF
260 extern void _start(void), etext(void); 285 extern void _start(void), etext(void);
261 monstartup((u_long)&_start, (u_long)&etext); 286 monstartup((u_long)&_start, (u_long)&etext);
262 #endif /* DEBUG_FORKGPROF */ 287 #endif /* DEBUG_FORKGPROF */
263 288
289 m_free(remote_addr_str);
264 addrstring = getaddrstring(&remoteaddr, 1); 290 addrstring = getaddrstring(&remoteaddr, 1);
265 dropbear_log(LOG_INFO, "Child connection from %s", addrstring); 291 dropbear_log(LOG_INFO, "Child connection from %s", addrstring);
266 292
267 if (setsid() < 0) { 293 if (setsid() < 0) {
268 dropbear_exit("setsid: %s", strerror(errno)); 294 dropbear_exit("setsid: %s", strerror(errno));
269 } 295 }
270 296
271 /* make sure we close sockets */ 297 /* make sure we close sockets */
272 for (i = 0; i < (unsigned int)listensockcount; i++) { 298 for (i = 0; i < listensockcount; i++) {
273 if (m_close(listensocks[i]) == DROPBEAR_FAILURE) { 299 m_close(listensocks[i]);
274 dropbear_exit("Couldn't close socket");
275 }
276 } 300 }
277 301
278 if (m_close(childpipe[0]) == DROPBEAR_FAILURE) { 302 m_close(childpipe[0]);
279 dropbear_exit("Couldn't close socket");
280 }
281 303
282 /* start the session */ 304 /* start the session */
283 svr_session(childsock, childpipe[1], 305 svr_session(childsock, childpipe[1],
284 getaddrhostname(&remoteaddr), 306 getaddrhostname(&remoteaddr),
285 addrstring); 307 addrstring);
286 /* don't return */ 308 /* don't return */
287 assert(0); 309 dropbear_assert(0);
288 } 310 }
289 311
290 /* parent */ 312 out:
291 childpipes[j] = childpipe[0]; 313 /* This section is important for the parent too */
292 if (m_close(childpipe[1]) == DROPBEAR_FAILURE 314 m_close(childsock);
293 || m_close(childsock) == DROPBEAR_FAILURE) { 315 if (remote_addr_str) {
294 dropbear_exit("Couldn't close socket"); 316 m_free(remote_addr_str);
295 } 317 }
296 } 318 }
297 } /* for(;;) loop */ 319 } /* for(;;) loop */
298 320
299 /* don't reach here */ 321 /* don't reach here */
357 } 379 }
358 380
359 /* Now we can setup the hostkeys - needs to be after logging is on, 381 /* Now we can setup the hostkeys - needs to be after logging is on,
360 * otherwise we might end up blatting error messages to the socket */ 382 * otherwise we might end up blatting error messages to the socket */
361 loadhostkeys(); 383 loadhostkeys();
384
385 seedrandom();
362 } 386 }
363 387
364 /* Set up listening sockets for all the requested ports */ 388 /* Set up listening sockets for all the requested ports */
365 static int listensockets(int *sock, int sockcount, int *maxfd) { 389 static size_t listensockets(int *sock, size_t sockcount, int *maxfd) {
366 390
367 unsigned int i; 391 unsigned int i;
368 char* errstring = NULL; 392 char* errstring = NULL;
369 unsigned int sockpos = 0; 393 size_t sockpos = 0;
370 int nsock; 394 int nsock;
371 395
372 TRACE(("listensockets: %d to try\n", svr_opts.portcount)) 396 TRACE(("listensockets: %d to try\n", svr_opts.portcount))
373 397
374 for (i = 0; i < svr_opts.portcount; i++) { 398 for (i = 0; i < svr_opts.portcount; i++) {
375 399
376 TRACE(("listening on '%s'", svr_opts.ports[i])) 400 TRACE(("listening on '%s'", svr_opts.ports[i]))
377 401
378 nsock = dropbear_listen(NULL, svr_opts.ports[i], &sock[sockpos], 402 nsock = dropbear_listen("", svr_opts.ports[i], &sock[sockpos],
379 sockcount - sockpos, 403 sockcount - sockpos,
380 &errstring, maxfd); 404 &errstring, maxfd);
381 405
382 if (nsock < 0) { 406 if (nsock < 0) {
383 dropbear_log(LOG_WARNING, "Failed listening on '%s': %s", 407 dropbear_log(LOG_WARNING, "Failed listening on '%s': %s",