comparison svr-main.c @ 118:5312ca05ed48 private-rez

propagate of 717950f4061f1123659ee87c7c168805af920ab7 and 839f98f136788cc1466e4641bf796f96040a085d from branch 'matt.dbclient.authpam' to 'matt.dbclient.rez'
author Matt Johnston <matt@ucc.asn.au>
date Sun, 12 Sep 2004 04:56:50 +0000
parents 775c6cbfe995
children 8c2b3506f112
comparison
equal deleted inserted replaced
57:3b2a5a1c4347 118:5312ca05ed48
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 *maxfd); 32 static int listensockets(int *sock, int 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 static void main_inetd();
37 static void main_noinetd();
38 static void commonsetup();
36 39
37 static int childpipes[MAX_UNAUTH_CLIENTS]; 40 static int childpipes[MAX_UNAUTH_CLIENTS];
38 41
39 #if defined(DBMULTI_dropbear) || !defined(DROPBEAR_MULTI) 42 #if defined(DBMULTI_dropbear) || !defined(DROPBEAR_MULTI)
40 #if defined(DBMULTI_dropbear) && defined(DROPBEAR_MULTI) 43 #if defined(DBMULTI_dropbear) && defined(DROPBEAR_MULTI)
42 #else 45 #else
43 int main(int argc, char ** argv) 46 int main(int argc, char ** argv)
44 #endif 47 #endif
45 { 48 {
46 49
50
51 _dropbear_exit = svr_dropbear_exit;
52 _dropbear_log = svr_dropbear_log;
53
54 /* get commandline options */
55 svr_getopts(argc, argv);
56
57 #ifdef INETD_MODE
58 /* service program mode */
59 if (svr_opts.inetdmode) {
60 main_inetd();
61 /* notreached */
62 }
63 #endif
64
65 #ifdef NON_INETD_MODE
66 main_noinetd();
67 /* notreached */
68 #endif
69
70 dropbear_exit("Compiled without normal mode, can't run without -i\n");
71 return -1;
72 }
73 #endif
74
75 #ifdef INETD_MODE
76 static void main_inetd() {
77
78 struct sockaddr_storage remoteaddr;
79 int remoteaddrlen;
80 char * addrstring = NULL;
81
82 /* Set up handlers, syslog */
83 commonsetup();
84
85 remoteaddrlen = sizeof(remoteaddr);
86 if (getpeername(0, (struct sockaddr*)&remoteaddr, &remoteaddrlen) < 0) {
87 dropbear_exit("Unable to getpeername: %s", strerror(errno));
88 }
89
90 /* In case our inetd was lax in logging source addresses */
91 addrstring = getaddrstring(&remoteaddr, 1);
92 dropbear_log(LOG_INFO, "Child connection from %s", addrstring);
93 m_free(addrstring);
94
95 /* Don't check the return value - it may just fail since inetd has
96 * already done setsid() after forking (xinetd on Darwin appears to do
97 * this */
98 setsid();
99
100 /* Start service program
101 * -1 is a dummy childpipe, just something we can close() without
102 * mattering. */
103 svr_session(0, -1, getaddrhostname(&remoteaddr));
104
105 /* notreached */
106 }
107 #endif /* INETD_MODE */
108
109 #ifdef NON_INETD_MODE
110 void main_noinetd() {
47 fd_set fds; 111 fd_set fds;
48 struct timeval seltimeout; 112 struct timeval seltimeout;
49 unsigned int i, j; 113 unsigned int i, j;
50 int val; 114 int val;
51 int maxsock = -1; 115 int maxsock = -1;
52 struct sockaddr remoteaddr; 116 struct sockaddr_storage remoteaddr;
53 int remoteaddrlen; 117 int remoteaddrlen;
54 int listensocks[MAX_LISTEN_ADDR]; 118 int listensocks[MAX_LISTEN_ADDR];
55 unsigned int listensockcount = 0; 119 int listensockcount = 0;
56 FILE * pidfile; 120 FILE *pidfile = NULL;
57 121
58 int childsock; 122 int childsock;
59 pid_t childpid; 123 pid_t childpid;
60 int childpipe[2]; 124 int childpipe[2];
61
62 struct sigaction sa_chld;
63
64 _dropbear_exit = svr_dropbear_exit;
65 _dropbear_log = svr_dropbear_log;
66
67 /* get commandline options */
68 svr_getopts(argc, argv);
69 125
70 /* fork */ 126 /* fork */
71 if (svr_opts.forkbg) { 127 if (svr_opts.forkbg) {
72 int closefds = 0; 128 int closefds = 0;
73 #ifndef DEBUG_TRACE 129 #ifndef DEBUG_TRACE
74 if (!svr_opts.usingsyslog) { 130 if (!svr_opts.usingsyslog) {
75 closefds = 1; 131 closefds = 1;
76 } 132 }
77 #endif 133 #endif
78 if (daemon(0, closefds) < 0) { 134 if (daemon(0, closefds) < 0) {
79 dropbear_exit("Failed to create background process: %s", 135 dropbear_exit("Failed to daemonize: %s", strerror(errno));
80 strerror(errno)); 136 }
81 } 137 }
82 } 138
83 139 commonsetup();
84 #ifndef DISABLE_SYSLOG 140
85 if (svr_opts.usingsyslog) {
86 startsyslog();
87 }
88 #endif
89 141
90 /* should be done after syslog is working */ 142 /* should be done after syslog is working */
91 if (svr_opts.forkbg) { 143 if (svr_opts.forkbg) {
92 dropbear_log(LOG_INFO, "Running in background"); 144 dropbear_log(LOG_INFO, "Running in background");
93 } else { 145 } else {
99 if (pidfile) { 151 if (pidfile) {
100 fprintf(pidfile, "%d\n", getpid()); 152 fprintf(pidfile, "%d\n", getpid());
101 fclose(pidfile); 153 fclose(pidfile);
102 } 154 }
103 155
104 /* set up cleanup handler */
105 if (signal(SIGINT, sigintterm_handler) == SIG_ERR ||
106 #ifndef DEBUG_VALGRIND
107 signal(SIGTERM, sigintterm_handler) == SIG_ERR ||
108 #endif
109 signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
110 dropbear_exit("signal() error");
111 }
112
113 /* catch and reap zombie children */
114 sa_chld.sa_handler = sigchld_handler;
115 sa_chld.sa_flags = SA_NOCLDSTOP;
116 if (sigaction(SIGCHLD, &sa_chld, NULL) < 0) {
117 dropbear_exit("signal() error");
118 }
119 if (signal(SIGSEGV, sigsegv_handler) == SIG_ERR) {
120 dropbear_exit("signal() error");
121 }
122
123 /* sockets to identify pre-authenticated clients */ 156 /* sockets to identify pre-authenticated clients */
124 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) { 157 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) {
125 childpipes[i] = -1; 158 childpipes[i] = -1;
126 } 159 }
127 160
128 /* Set up the listening sockets */ 161 /* Set up the listening sockets */
129 /* XXX XXX ports */ 162 /* XXX XXX ports */
130 listensockcount = listensockets(listensocks, &maxsock); 163 listensockcount = listensockets(listensocks, MAX_LISTEN_ADDR, &maxsock);
164 if (listensockcount < 0) {
165 dropbear_exit("No listening ports available.");
166 }
131 167
132 /* incoming connection select loop */ 168 /* incoming connection select loop */
133 for(;;) { 169 for(;;) {
134 170
135 FD_ZERO(&fds); 171 FD_ZERO(&fds);
136 172
137 seltimeout.tv_sec = 60; 173 seltimeout.tv_sec = 60;
138 seltimeout.tv_usec = 0; 174 seltimeout.tv_usec = 0;
139 175
140 /* listening sockets */ 176 /* listening sockets */
141 for (i = 0; i < listensockcount; i++) { 177 for (i = 0; i < (unsigned int)listensockcount; i++) {
142 FD_SET(listensocks[i], &fds); 178 FD_SET(listensocks[i], &fds);
143 } 179 }
144 180
145 /* pre-authentication clients */ 181 /* pre-authentication clients */
146 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) { 182 for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) {
177 childpipes[i] = -1; 213 childpipes[i] = -1;
178 } 214 }
179 } 215 }
180 216
181 /* handle each socket which has something to say */ 217 /* handle each socket which has something to say */
182 for (i = 0; i < listensockcount; i++) { 218 for (i = 0; i < (unsigned int)listensockcount; i++) {
183 if (!FD_ISSET(listensocks[i], &fds)) 219 if (!FD_ISSET(listensocks[i], &fds))
184 continue; 220 continue;
185 221
186 /* child connection XXX - ip6 stuff here */ 222 remoteaddrlen = sizeof(remoteaddr);
187 remoteaddrlen = sizeof(struct sockaddr_in); 223 childsock = accept(listensocks[i],
188 childsock = accept(listensocks[i], &remoteaddr, &remoteaddrlen); 224 (struct sockaddr*)&remoteaddr, &remoteaddrlen);
189 225
190 if (childsock < 0) { 226 if (childsock < 0) {
191 /* accept failed */ 227 /* accept failed */
192 continue; 228 continue;
193 } 229 }
220 #ifdef DEBUG_FORKGPROF 256 #ifdef DEBUG_FORKGPROF
221 extern void _start(void), etext(void); 257 extern void _start(void), etext(void);
222 monstartup((u_long)&_start, (u_long)&etext); 258 monstartup((u_long)&_start, (u_long)&etext);
223 #endif /* DEBUG_FORKGPROF */ 259 #endif /* DEBUG_FORKGPROF */
224 260
225 addrstring = getaddrstring(&remoteaddr); 261 addrstring = getaddrstring(&remoteaddr, 1);
226 dropbear_log(LOG_INFO, "Child connection from %s", addrstring); 262 dropbear_log(LOG_INFO, "Child connection from %s", addrstring);
227 m_free(addrstring); 263 m_free(addrstring);
228 264
229 if (setsid() < 0) { 265 if (setsid() < 0) {
230 dropbear_exit("setsid: %s", strerror(errno)); 266 dropbear_exit("setsid: %s", strerror(errno));
231 } 267 }
232 268
233 /* make sure we close sockets */ 269 /* make sure we close sockets */
234 for (i = 0; i < listensockcount; i++) { 270 for (i = 0; i < (unsigned int)listensockcount; i++) {
235 if (m_close(listensocks[i]) == DROPBEAR_FAILURE) { 271 if (m_close(listensocks[i]) == DROPBEAR_FAILURE) {
236 dropbear_exit("Couldn't close socket"); 272 dropbear_exit("Couldn't close socket");
237 } 273 }
238 } 274 }
239 275
256 } 292 }
257 } 293 }
258 } /* for(;;) loop */ 294 } /* for(;;) loop */
259 295
260 /* don't reach here */ 296 /* don't reach here */
261 return -1; 297 }
262 } 298 #endif /* NON_INETD_MODE */
263 #endif 299
264 300
265 /* catch + reap zombie children */ 301 /* catch + reap zombie children */
266 static void sigchld_handler(int fish) { 302 static void sigchld_handler(int UNUSED(unused)) {
267 struct sigaction sa_chld; 303 struct sigaction sa_chld;
268 304
269 while(waitpid(-1, NULL, WNOHANG) > 0); 305 while(waitpid(-1, NULL, WNOHANG) > 0);
270 306
271 sa_chld.sa_handler = sigchld_handler; 307 sa_chld.sa_handler = sigchld_handler;
274 dropbear_exit("signal() error"); 310 dropbear_exit("signal() error");
275 } 311 }
276 } 312 }
277 313
278 /* catch any segvs */ 314 /* catch any segvs */
279 static void sigsegv_handler(int fish) { 315 static void sigsegv_handler(int UNUSED(unused)) {
280 fprintf(stderr, "Aiee, segfault! You should probably report " 316 fprintf(stderr, "Aiee, segfault! You should probably report "
281 "this as a bug to the developer\n"); 317 "this as a bug to the developer\n");
282 exit(EXIT_FAILURE); 318 exit(EXIT_FAILURE);
283 } 319 }
284 320
285 /* catch ctrl-c or sigterm */ 321 /* catch ctrl-c or sigterm */
286 static void sigintterm_handler(int fish) { 322 static void sigintterm_handler(int UNUSED(unused)) {
287 323
288 exitflag = 1; 324 exitflag = 1;
289 } 325 }
290 326
327 /* Things used by inetd and non-inetd modes */
328 static void commonsetup() {
329
330 struct sigaction sa_chld;
331 #ifndef DISABLE_SYSLOG
332 if (svr_opts.usingsyslog) {
333 startsyslog();
334 }
335 #endif
336
337 /* set up cleanup handler */
338 if (signal(SIGINT, sigintterm_handler) == SIG_ERR ||
339 #ifndef DEBUG_VALGRIND
340 signal(SIGTERM, sigintterm_handler) == SIG_ERR ||
341 #endif
342 signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
343 dropbear_exit("signal() error");
344 }
345
346 /* catch and reap zombie children */
347 sa_chld.sa_handler = sigchld_handler;
348 sa_chld.sa_flags = SA_NOCLDSTOP;
349 if (sigaction(SIGCHLD, &sa_chld, NULL) < 0) {
350 dropbear_exit("signal() error");
351 }
352 if (signal(SIGSEGV, sigsegv_handler) == SIG_ERR) {
353 dropbear_exit("signal() error");
354 }
355
356 /* Now we can setup the hostkeys - needs to be after logging is on,
357 * otherwise we might end up blatting error messages to the socket */
358 loadhostkeys();
359 }
360
291 /* Set up listening sockets for all the requested ports */ 361 /* Set up listening sockets for all the requested ports */
292 static int listensockets(int *sock, int *maxfd) { 362 static int listensockets(int *sock, int sockcount, int *maxfd) {
293 363
294 int listensock; /* listening fd */
295 struct sockaddr_in listen_addr;
296 struct linger linger;
297 unsigned int i; 364 unsigned int i;
298 int val; 365 char* errstring = NULL;
366 unsigned int sockpos = 0;
367 int nsock;
368
369 TRACE(("listensockets: %d to try\n", svr_opts.portcount));
299 370
300 for (i = 0; i < svr_opts.portcount; i++) { 371 for (i = 0; i < svr_opts.portcount; i++) {
301 372
302 /* iterate through all the sockets to listen on */ 373 TRACE(("listening on '%s'", svr_opts.ports[i]));
303 listensock = socket(PF_INET, SOCK_STREAM, 0); 374
304 if (listensock < 0) { 375 nsock = dropbear_listen(NULL, svr_opts.ports[i], &sock[sockpos],
305 dropbear_exit("Failed to create socket"); 376 sockcount - sockpos,
306 } 377 &errstring, maxfd);
307 378
308 val = 1; 379 if (nsock < 0) {
309 /* set to reuse, quick timeout */ 380 dropbear_log(LOG_WARNING, "Failed listening on '%s': %s",
310 setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR, 381 svr_opts.ports[i], errstring);
311 (void*) &val, sizeof(val)); 382 m_free(errstring);
312 linger.l_onoff = 1; 383 continue;
313 linger.l_linger = 5; 384 }
314 setsockopt(listensock, SOL_SOCKET, SO_LINGER, 385
315 (void*)&linger, sizeof(linger)); 386 sockpos += nsock;
316 387
317 /* disable nagle */ 388 }
318 setsockopt(listensock, IPPROTO_TCP, TCP_NODELAY, 389 return sockpos;
319 (void*)&val, sizeof(val)); 390 }
320
321 memset((void*)&listen_addr, 0x0, sizeof(listen_addr));
322 listen_addr.sin_family = AF_INET;
323 listen_addr.sin_port = htons(svr_opts.ports[i]);
324 listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
325 memset(&(listen_addr.sin_zero), '\0', 8);
326
327 if (bind(listensock, (struct sockaddr *)&listen_addr,
328 sizeof(listen_addr)) < 0) {
329 dropbear_exit("Bind failed port %d", svr_opts.ports[i]);
330 }
331
332 /* listen */
333 if (listen(listensock, 20) < 0) { /* TODO set listen count */
334 dropbear_exit("Listen failed");
335 }
336
337 /* nonblock */
338 if (fcntl(listensock, F_SETFL, O_NONBLOCK) < 0) {
339 dropbear_exit("Failed to set non-blocking");
340 }
341
342 sock[i] = listensock;
343 *maxfd = MAX(listensock, *maxfd);
344 }
345
346 return svr_opts.portcount;
347 }