1 /*
2  * ProFTPD - FTP server daemon
3  * Copyright (c) 1997, 1998 Public Flood Software
4  * Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver@tos.net>
5  * Copyright (c) 2001-2020 The ProFTPD Project team
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
20  *
21  * As a special exemption, Public Flood Software/MacGyver aka Habeeb J. Dihu
22  * and other respective copyright holders give permission to link this program
23  * with OpenSSL, and distribute the resulting executable, without including
24  * the source code for OpenSSL in the source distribution.
25  */
26 
27 /* House initialization and main program loop */
28 
29 #include "conf.h"
30 
31 #ifdef HAVE_GETOPT_H
32 # include <getopt.h>
33 #endif
34 
35 #ifdef HAVE_LIBUTIL_H
36 # include <libutil.h>
37 #endif /* HAVE_LIBUTIL_H */
38 
39 #ifdef HAVE_UNAME
40 # include <sys/utsname.h>
41 #endif
42 
43 #include "privs.h"
44 
45 #ifdef PR_USE_OPENSSL
46 # include <openssl/opensslv.h>
47 #endif /* PR_USE_OPENSSL */
48 
49 int (*cmd_auth_chk)(cmd_rec *);
50 void (*cmd_handler)(server_rec *, conn_t *);
51 
52 /* From modules/module_glue.c */
53 extern module *static_modules[];
54 
55 extern int have_dead_child;
56 extern xaset_t *server_list;
57 
58 unsigned long max_connects = 0UL;
59 unsigned int max_connect_interval = 1;
60 
61 session_t session;
62 
63 /* Is this process the master standalone daemon process? */
64 unsigned char is_master = TRUE;
65 
66 pid_t mpid = 0;				/* Master pid */
67 
68 uid_t daemon_uid;
69 gid_t daemon_gid;
70 array_header *daemon_gids;
71 
72 static time_t shut = 0, deny = 0, disc = 0;
73 static char shutmsg[81] = {'\0'};
74 
75 /* The default command buffer size SHOULD be large enough to handle the
76  * maximum path length, plus 4 bytes for the FTP command, plus 1 for the
77  * whitespace separating command from path, and 2 for the terminating CRLF.
78  */
79 #define PR_DEFAULT_CMD_BUFSZ	(PR_TUNABLE_PATH_MAX + 7)
80 
81 /* From response.c */
82 extern pr_response_t *resp_list, *resp_err_list;
83 
84 int nodaemon = 0;
85 
86 static int no_forking = FALSE;
87 static int quiet = 0;
88 static int shutting_down = 0;
89 static int syntax_check = 0;
90 
91 /* Command handling */
92 static void cmd_loop(server_rec *s, conn_t *conn);
93 
94 static cmd_rec *make_ftp_cmd(pool *p, char *buf, size_t buflen, int flags);
95 
96 static const char *config_filename = PR_CONFIG_FILE_PATH;
97 
98 /* Add child semaphore fds into the rfd for selecting */
semaphore_fds(fd_set * rfd,int maxfd)99 static int semaphore_fds(fd_set *rfd, int maxfd) {
100   if (child_count()) {
101     pr_child_t *ch;
102 
103     for (ch = child_get(NULL); ch; ch = child_get(ch)) {
104       pr_signals_handle();
105 
106       if (ch->ch_pipefd != -1) {
107         FD_SET(ch->ch_pipefd, rfd);
108         if (ch->ch_pipefd > maxfd) {
109           maxfd = ch->ch_pipefd;
110         }
111       }
112     }
113   }
114 
115   return maxfd;
116 }
117 
set_auth_check(int (* chk)(cmd_rec *))118 void set_auth_check(int (*chk)(cmd_rec*)) {
119   cmd_auth_chk = chk;
120 }
121 
pr_cmd_set_handler(void (* handler)(server_rec *,conn_t *))122 void pr_cmd_set_handler(void (*handler)(server_rec *, conn_t *)) {
123   if (handler == NULL) {
124     cmd_handler = cmd_loop;
125 
126   } else {
127     cmd_handler = handler;
128   }
129 }
130 
session_exit(int pri,void * lv,int exitval,void * dummy)131 void session_exit(int pri, void *lv, int exitval, void *dummy) {
132   char *msg = (char *) lv;
133 
134   pr_log_pri(pri, "%s", msg);
135 
136   if (ServerType == SERVER_STANDALONE &&
137       is_master) {
138     pr_log_pri(PR_LOG_NOTICE, "ProFTPD " PROFTPD_VERSION_TEXT
139       " standalone mode SHUTDOWN");
140 
141     PRIVS_ROOT
142     pr_delete_scoreboard();
143     if (!nodaemon)
144       pr_pidfile_remove();
145     PRIVS_RELINQUISH
146   }
147 
148   pr_session_end(0);
149 }
150 
shutdown_end_session(void * d1,void * d2,void * d3,void * d4)151 void shutdown_end_session(void *d1, void *d2, void *d3, void *d4) {
152   pool *p = permanent_pool;
153 
154   if (check_shutmsg(p, PR_SHUTMSG_PATH, &shut, &deny, &disc, shutmsg,
155       sizeof(shutmsg)) == 1) {
156     const char *user;
157     time_t now;
158     const char *msg, *serveraddress;
159     config_rec *c = NULL;
160     unsigned char *authenticated = get_param_ptr(main_server->conf,
161       "authenticated", FALSE);
162 
163     serveraddress = (session.c && session.c->local_addr) ?
164       pr_netaddr_get_ipstr(session.c->local_addr) :
165       main_server->ServerAddress;
166 
167     c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress", FALSE);
168     if (c != NULL) {
169       pr_netaddr_t *masq_addr = NULL;
170 
171       if (c->argv[0] != NULL) {
172         masq_addr = c->argv[0];
173       }
174 
175       if (masq_addr != NULL) {
176         serveraddress = pr_netaddr_get_ipstr(masq_addr);
177       }
178     }
179 
180     time(&now);
181     if (authenticated && *authenticated == TRUE) {
182       user = pr_table_get(session.notes, "mod_auth.orig-user", NULL);
183 
184     } else {
185       user = "NONE";
186     }
187 
188     msg = sreplace(p, shutmsg,
189                    "%s", pstrdup(p, pr_strtime3(p, shut, FALSE)),
190                    "%r", pstrdup(p, pr_strtime3(p, deny, FALSE)),
191                    "%d", pstrdup(p, pr_strtime3(p, disc, FALSE)),
192 		   "%C", (session.cwd[0] ? session.cwd : "(none)"),
193 		   "%L", serveraddress,
194 		   "%R", (session.c && session.c->remote_name ?
195                          session.c->remote_name : "(unknown)"),
196 		   "%T", pstrdup(p, pr_strtime3(p, now, FALSE)),
197 		   "%U", user,
198 		   "%V", main_server->ServerName,
199                    NULL );
200 
201     pr_response_send_async(R_421, _("FTP server shutting down - %s"), msg);
202 
203     pr_log_pri(PR_LOG_NOTICE, "%s", msg);
204     pr_session_disconnect(NULL, PR_SESS_DISCONNECT_SERVER_SHUTDOWN, NULL);
205   }
206 
207   if (signal(SIGUSR1, pr_signals_handle_disconnect) == SIG_ERR) {
208     pr_log_pri(PR_LOG_NOTICE,
209       "unable to install SIGUSR1 (signal %d) handler: %s", SIGUSR1,
210       strerror(errno));
211   }
212 }
213 
get_command_class(const char * name)214 static int get_command_class(const char *name) {
215   int idx = -1;
216   unsigned int hash = 0;
217   cmdtable *c;
218 
219   c = pr_stash_get_symbol2(PR_SYM_CMD, name, NULL, &idx, &hash);
220   while (c && c->cmd_type != CMD) {
221     pr_signals_handle();
222     c = pr_stash_get_symbol2(PR_SYM_CMD, name, c, &idx, &hash);
223   }
224 
225   /* By default, every command has a class of CL_ALL.  This insures that
226    * any configured ExtendedLogs that default to "all" will log the command.
227    */
228   return (c ? c->cmd_class : CL_ALL);
229 }
230 
_dispatch(cmd_rec * cmd,int cmd_type,int validate,char * match)231 static int _dispatch(cmd_rec *cmd, int cmd_type, int validate, char *match) {
232   const char *cmdargstr = NULL;
233   cmdtable *c;
234   modret_t *mr;
235   int success = 0, xerrno = 0;
236   int send_error = 0;
237   static int match_index_cache = -1;
238   static unsigned int match_hash_cache = 0;
239   static char *last_match = NULL;
240   int *index_cache = NULL;
241   unsigned int *hash_cache = NULL;
242 
243   send_error = (cmd_type == PRE_CMD || cmd_type == CMD ||
244     cmd_type == POST_CMD_ERR);
245 
246   if (!match) {
247     match = cmd->argv[0];
248     index_cache = &cmd->stash_index;
249     hash_cache = &cmd->stash_hash;
250 
251   } else {
252     if (last_match != match) {
253       match_index_cache = -1;
254       last_match = match;
255     }
256 
257     index_cache = &match_index_cache;
258     hash_cache = &match_hash_cache;
259   }
260 
261   c = pr_stash_get_symbol2(PR_SYM_CMD, match, NULL, index_cache, hash_cache);
262 
263   while (c && !success) {
264     size_t cmdargstrlen = 0;
265 
266     pr_signals_handle();
267 
268     session.curr_cmd = cmd->argv[0];
269     session.curr_cmd_id = cmd->cmd_id;
270     session.curr_cmd_rec = cmd;
271     session.curr_phase = cmd_type;
272 
273     if (c->cmd_type == cmd_type) {
274       if (c->group) {
275         cmd->group = pstrdup(cmd->pool, c->group);
276       }
277 
278       if (c->requires_auth &&
279           cmd_auth_chk &&
280           !cmd_auth_chk(cmd)) {
281         pr_trace_msg("command", 8,
282           "command '%s' failed 'requires_auth' check for mod_%s.c",
283           (char *) cmd->argv[0], c->m->name);
284         errno = EACCES;
285         return -1;
286       }
287 
288       if (cmd->tmp_pool == NULL) {
289         cmd->tmp_pool = make_sub_pool(cmd->pool);
290         pr_pool_tag(cmd->tmp_pool, "cmd_rec tmp pool");
291       }
292 
293       cmdargstr = pr_cmd_get_displayable_str(cmd, &cmdargstrlen);
294 
295       if (cmd_type == CMD) {
296 
297         /* The client has successfully authenticated... */
298         if (session.user) {
299           char *args = NULL;
300 
301           /* Be defensive, and check whether cmdargstrlen has a value.
302            * If it's zero, assume we need to use strchr(3), rather than
303            * memchr(2); see Bug#3714.
304            */
305           if (cmdargstrlen > 0) {
306             args = memchr(cmdargstr, ' ', cmdargstrlen);
307 
308           } else {
309             args = strchr(cmdargstr, ' ');
310           }
311 
312           pr_scoreboard_entry_update(session.pid,
313             PR_SCORE_CMD, "%s", cmd->argv[0], NULL, NULL);
314           pr_scoreboard_entry_update(session.pid,
315             PR_SCORE_CMD_ARG, "%s", args ? (args + 1) : "", NULL, NULL);
316 
317           pr_proctitle_set("%s - %s: %s", session.user, session.proc_prefix,
318             cmdargstr);
319 
320         /* ...else the client has not yet authenticated */
321         } else {
322           pr_proctitle_set("%s:%d: %s", session.c->remote_addr ?
323             pr_netaddr_get_ipstr(session.c->remote_addr) : "?",
324             session.c->remote_port ? session.c->remote_port : 0, cmdargstr);
325         }
326       }
327 
328       /* Skip logging the internal CONNECT/DISCONNECT commands. */
329       if (!(cmd->cmd_class & CL_CONNECT) &&
330           !(cmd->cmd_class & CL_DISCONNECT)) {
331 
332         pr_log_debug(DEBUG4, "dispatching %s command '%s' to mod_%s",
333           (cmd_type == PRE_CMD ? "PRE_CMD" :
334            cmd_type == CMD ? "CMD" :
335            cmd_type == POST_CMD ? "POST_CMD" :
336            cmd_type == POST_CMD_ERR ? "POST_CMD_ERR" :
337            cmd_type == LOG_CMD ? "LOG_CMD" :
338            cmd_type == LOG_CMD_ERR ? "LOG_CMD_ERR" :
339            "(unknown)"),
340           cmdargstr, c->m->name);
341 
342         pr_trace_msg("command", 7, "dispatching %s command '%s' to mod_%s.c",
343           (cmd_type == PRE_CMD ? "PRE_CMD" :
344            cmd_type == CMD ? "CMD" :
345            cmd_type == POST_CMD ? "POST_CMD" :
346            cmd_type == POST_CMD_ERR ? "POST_CMD_ERR" :
347            cmd_type == LOG_CMD ? "LOG_CMD" :
348            cmd_type == LOG_CMD_ERR ? "LOG_CMD_ERR" :
349            "(unknown)"),
350           cmdargstr, c->m->name);
351       }
352 
353       cmd->cmd_class |= c->cmd_class;
354 
355       /* KLUDGE: disable umask() for not G_WRITE operations.  Config/
356        * Directory walking code will be completely redesigned in 1.3,
357        * this is only necessary for performance reasons in 1.1/1.2
358        */
359 
360       if (!c->group || strcmp(c->group, G_WRITE) != 0)
361         kludge_disable_umask();
362       mr = pr_module_call(c->m, c->handler, cmd);
363       kludge_enable_umask();
364 
365       if (MODRET_ISHANDLED(mr)) {
366         success = 1;
367 
368       } else if (MODRET_ISERROR(mr)) {
369         xerrno = errno;
370         success = -1;
371 
372         if (cmd_type == POST_CMD ||
373             cmd_type == LOG_CMD ||
374             cmd_type == LOG_CMD_ERR) {
375           if (MODRET_ERRMSG(mr)) {
376             pr_log_pri(PR_LOG_NOTICE, "%s", MODRET_ERRMSG(mr));
377           }
378 
379           /* Even though we normally want to return a negative value
380            * for success (indicating lack of success), for
381            * LOG_CMD/LOG_CMD_ERR handlers, we always want to handle
382            * errors as a success value of zero (meaning "keep looking").
383            *
384            * This will allow the cmd_rec to continue to be dispatched to
385            * the other interested handlers (Bug#3633).
386            */
387           if (cmd_type == LOG_CMD ||
388               cmd_type == LOG_CMD_ERR) {
389             success = 0;
390           }
391 
392         } else if (send_error) {
393           if (MODRET_ERRNUM(mr) &&
394               MODRET_ERRMSG(mr)) {
395             pr_response_add_err(MODRET_ERRNUM(mr), "%s", MODRET_ERRMSG(mr));
396 
397           } else if (MODRET_ERRMSG(mr)) {
398             pr_response_send_raw("%s", MODRET_ERRMSG(mr));
399           }
400         }
401 
402         errno = xerrno;
403       }
404 
405       if (session.user &&
406           !(session.sf_flags & SF_XFER) &&
407           cmd_type == CMD) {
408         pr_session_set_idle();
409       }
410 
411       destroy_pool(cmd->tmp_pool);
412       cmd->tmp_pool = NULL;
413     }
414 
415     if (!success) {
416       c = pr_stash_get_symbol2(PR_SYM_CMD, match, c, index_cache, hash_cache);
417     }
418   }
419 
420   /* Note: validate is only TRUE for the CMD phase, for specific handlers
421    * (as opposed to any C_ANY handlers).
422    */
423 
424   if (!c &&
425       !success &&
426       validate) {
427     char *method;
428 
429     /* Prettify the command method, if need be. */
430     if (strchr(cmd->argv[0], '_') == NULL) {
431       method = cmd->argv[0];
432 
433     } else {
434       register unsigned int i;
435 
436       method = pstrdup(cmd->pool, cmd->argv[0]);
437       for (i = 0; method[i]; i++) {
438         if (method[i] == '_')
439           method[i] = ' ';
440       }
441     }
442 
443     pr_event_generate("core.unhandled-command", cmd);
444 
445     pr_response_add_err(R_500, _("%s not understood"), method);
446     success = -1;
447   }
448 
449   return success;
450 }
451 
452 /* Returns the appropriate maximum buffer size to use for FTP commands
453  * from the client.
454  */
get_max_cmd_sz(void)455 static size_t get_max_cmd_sz(void) {
456   size_t res;
457   size_t *bufsz = NULL;
458 
459   bufsz = get_param_ptr(main_server->conf, "CommandBufferSize", FALSE);
460   if (bufsz == NULL) {
461     res = PR_DEFAULT_CMD_BUFSZ;
462 
463   } else {
464     pr_log_debug(DEBUG1, "setting CommandBufferSize to %lu",
465       (unsigned long) *bufsz);
466     res = *bufsz;
467   }
468 
469   return res;
470 }
471 
pr_cmd_read(cmd_rec ** res)472 int pr_cmd_read(cmd_rec **res) {
473   static long cmd_bufsz = -1;
474   static char *cmd_buf = NULL;
475   int cmd_buflen;
476   unsigned int too_large_count = 0;
477   char *ptr;
478 
479   if (res == NULL) {
480     errno = EINVAL;
481     return -1;
482   }
483 
484   if (cmd_bufsz == -1) {
485     cmd_bufsz = get_max_cmd_sz();
486   }
487 
488   if (cmd_buf == NULL) {
489     cmd_buf = pcalloc(session.pool, cmd_bufsz + 1);
490   }
491 
492   while (TRUE) {
493     pr_signals_handle();
494 
495     memset(cmd_buf, '\0', cmd_bufsz);
496 
497     cmd_buflen = pr_netio_telnet_gets2(cmd_buf, cmd_bufsz, session.c->instrm,
498       session.c->outstrm);
499     if (cmd_buflen < 0) {
500       if (errno == E2BIG) {
501         /* The client sent a too-long command which was ignored; give
502          * them a few more chances, with minor delays?
503          */
504         too_large_count++;
505         pr_timer_usleep(250 * 1000);
506 
507         if (too_large_count > 3) {
508           return -1;
509         }
510 
511         continue;
512       }
513 
514       if (session.c->instrm->strm_errno == 0) {
515         pr_trace_msg("command", 6,
516           "client sent EOF, closing control connection");
517       }
518 
519       return -1;
520     }
521 
522     break;
523   }
524 
525   /* If the read length is less than the cmd_bufsz, then there is no need to
526    * truncate the buffer by inserting a NUL.
527    */
528   if (cmd_buflen > cmd_bufsz) {
529     pr_log_debug(DEBUG0, "truncating incoming command length (%d bytes) to "
530       "CommandBufferSize %lu; use the CommandBufferSize directive to increase "
531       "the allowed command length", cmd_buflen, (unsigned long) cmd_bufsz);
532     cmd_buf[cmd_bufsz-1] = '\0';
533   }
534 
535   if (cmd_buflen > 0 &&
536       (cmd_buf[cmd_buflen-1] == '\n' || cmd_buf[cmd_buflen-1] == '\r')) {
537     cmd_buf[cmd_buflen-1] = '\0';
538     cmd_buflen--;
539 
540     if (cmd_buflen > 0 &&
541         (cmd_buf[cmd_buflen-1] == '\n' || cmd_buf[cmd_buflen-1] =='\r')) {
542       cmd_buf[cmd_buflen-1] = '\0';
543       cmd_buflen--;
544     }
545   }
546 
547   ptr = cmd_buf;
548   if (*ptr == '\r') {
549     ptr++;
550   }
551 
552   if (*ptr) {
553     int flags = 0;
554     cmd_rec *cmd;
555 
556     /* If this is a SITE command, preserve embedded whitespace in the
557      * command parameters, in order to handle file names that have multiple
558      * spaces in the names.  Arguably this should be handled in the SITE
559      * command handlers themselves, via cmd->arg.  This small hack
560      * reduces the burden on SITE module developers, however.
561      */
562     if (strncasecmp(ptr, C_SITE, 4) == 0) {
563       flags |= PR_STR_FL_PRESERVE_WHITESPACE;
564     }
565 
566     cmd = make_ftp_cmd(session.pool, ptr, cmd_buflen, flags);
567     if (cmd != NULL) {
568       *res = cmd;
569 
570       if (pr_cmd_is_http(cmd) == TRUE) {
571         cmd->is_ftp = FALSE;
572         cmd->protocol = "HTTP";
573 
574       } else if (pr_cmd_is_ssh2(cmd) == TRUE) {
575         cmd->is_ftp = FALSE;
576         cmd->protocol = "SSH2";
577 
578       } else if (pr_cmd_is_smtp(cmd) == TRUE) {
579         cmd->is_ftp = FALSE;
580         cmd->protocol = "SMTP";
581 
582       } else {
583         /* Assume that the client is sending valid FTP commands. */
584         cmd->is_ftp = TRUE;
585         cmd->protocol = "FTP";
586       }
587     }
588   }
589 
590   return 0;
591 }
592 
set_cmd_start_ms(cmd_rec * cmd)593 static int set_cmd_start_ms(cmd_rec *cmd) {
594   void *v;
595   uint64_t start_ms;
596 
597   if (cmd->notes == NULL) {
598     return 0;
599   }
600 
601   v = (void *) pr_table_get(cmd->notes, "start_ms", NULL);
602   if (v != NULL) {
603     return 0;
604   }
605 
606   if (pr_gettimeofday_millis(&start_ms) < 0) {
607     return -1;
608   }
609 
610   v = palloc(cmd->pool, sizeof(uint64_t));
611   memcpy(v, &start_ms, sizeof(uint64_t));
612 
613   return pr_table_add(cmd->notes, "start_ms", v, sizeof(uint64_t));
614 }
615 
pr_cmd_dispatch_phase(cmd_rec * cmd,int phase,int flags)616 int pr_cmd_dispatch_phase(cmd_rec *cmd, int phase, int flags) {
617   char *cp = NULL;
618   int success = 0, xerrno = 0;
619   pool *resp_pool = NULL;
620 
621   if (cmd == NULL) {
622     errno = EINVAL;
623     return -1;
624   }
625 
626   cmd->server = main_server;
627 
628   if (flags & PR_CMD_DISPATCH_FL_CLEAR_RESPONSE) {
629     /* Skip logging the internal CONNECT/DISCONNECT commands. */
630     if (!(cmd->cmd_class & CL_CONNECT) &&
631         !(cmd->cmd_class & CL_DISCONNECT)) {
632       pr_trace_msg("response", 9,
633         "clearing response lists before dispatching command '%s'",
634         (char *) cmd->argv[0]);
635     }
636     pr_response_clear(&resp_list);
637     pr_response_clear(&resp_err_list);
638   }
639 
640   /* Get any previous pool that may be being used by the Response API.
641    *
642    * In most cases, this will be NULL.  However, if proftpd is in the
643    * midst of a data transfer when a command comes in on the control
644    * connection, then the pool in use will be that of the data transfer
645    * instigating command.  We want to stash that pool, so that after this
646    * command is dispatched, we can return the pool of the old command.
647    * Otherwise, Bad Things (segfaults) happen.
648    */
649   resp_pool = pr_response_get_pool();
650 
651   /* Set the pool used by the Response API for this command. */
652   pr_response_set_pool(cmd->pool);
653 
654   for (cp = cmd->argv[0]; *cp; cp++) {
655     *cp = toupper(*cp);
656   }
657 
658   if (cmd->cmd_class == 0) {
659     cmd->cmd_class = get_command_class(cmd->argv[0]);
660   }
661 
662   if (cmd->cmd_id == 0) {
663     cmd->cmd_id = pr_cmd_get_id(cmd->argv[0]);
664   }
665 
666   set_cmd_start_ms(cmd);
667 
668   if (phase == 0) {
669     /* First, dispatch to wildcard PRE_CMD handlers. */
670     success = _dispatch(cmd, PRE_CMD, FALSE, C_ANY);
671 
672     if (!success)	/* run other pre_cmd */
673       success = _dispatch(cmd, PRE_CMD, FALSE, NULL);
674 
675     if (success < 0) {
676       /* Dispatch to POST_CMD_ERR handlers as well. */
677 
678       _dispatch(cmd, POST_CMD_ERR, FALSE, C_ANY);
679       _dispatch(cmd, POST_CMD_ERR, FALSE, NULL);
680 
681       _dispatch(cmd, LOG_CMD_ERR, FALSE, C_ANY);
682       _dispatch(cmd, LOG_CMD_ERR, FALSE, NULL);
683 
684       xerrno = errno;
685       pr_trace_msg("response", 9, "flushing error response list for '%s'",
686         (char *) cmd->argv[0]);
687       pr_response_flush(&resp_err_list);
688 
689       /* Restore any previous pool to the Response API. */
690       pr_response_set_pool(resp_pool);
691 
692       errno = xerrno;
693       return success;
694     }
695 
696     success = _dispatch(cmd, CMD, FALSE, C_ANY);
697     if (!success)
698       success = _dispatch(cmd, CMD, TRUE, NULL);
699 
700     if (success == 1) {
701       success = _dispatch(cmd, POST_CMD, FALSE, C_ANY);
702       if (!success)
703         success = _dispatch(cmd, POST_CMD, FALSE, NULL);
704 
705       _dispatch(cmd, LOG_CMD, FALSE, C_ANY);
706       _dispatch(cmd, LOG_CMD, FALSE, NULL);
707 
708       xerrno = errno;
709       pr_trace_msg("response", 9, "flushing response list for '%s'",
710         (char *) cmd->argv[0]);
711       pr_response_flush(&resp_list);
712 
713       errno = xerrno;
714 
715     } else if (success < 0) {
716       /* Allow for non-logging command handlers to be run if CMD fails. */
717 
718       success = _dispatch(cmd, POST_CMD_ERR, FALSE, C_ANY);
719       if (!success)
720         success = _dispatch(cmd, POST_CMD_ERR, FALSE, NULL);
721 
722       _dispatch(cmd, LOG_CMD_ERR, FALSE, C_ANY);
723       _dispatch(cmd, LOG_CMD_ERR, FALSE, NULL);
724 
725       xerrno = errno;
726       pr_trace_msg("response", 9, "flushing error response list for '%s'",
727         (char *) cmd->argv[0]);
728       pr_response_flush(&resp_err_list);
729 
730       errno = xerrno;
731     }
732 
733   } else {
734     switch (phase) {
735       case PRE_CMD:
736       case POST_CMD:
737       case POST_CMD_ERR:
738         success = _dispatch(cmd, phase, FALSE, C_ANY);
739         if (!success) {
740           success = _dispatch(cmd, phase, FALSE, NULL);
741           xerrno = errno;
742         }
743         break;
744 
745       case CMD:
746         success = _dispatch(cmd, phase, FALSE, C_ANY);
747         if (!success)
748           success = _dispatch(cmd, phase, TRUE, NULL);
749         break;
750 
751       case LOG_CMD:
752       case LOG_CMD_ERR:
753         (void) _dispatch(cmd, phase, FALSE, C_ANY);
754         (void) _dispatch(cmd, phase, FALSE, NULL);
755         break;
756 
757       default:
758         /* Restore any previous pool to the Response API. */
759         pr_response_set_pool(resp_pool);
760 
761         errno = EINVAL;
762         return -1;
763     }
764 
765     if (flags & PR_CMD_DISPATCH_FL_SEND_RESPONSE) {
766       xerrno = errno;
767 
768       if (success == 1) {
769         pr_trace_msg("response", 9, "flushing response list for '%s'",
770           (char *) cmd->argv[0]);
771         pr_response_flush(&resp_list);
772 
773       } else if (success < 0) {
774         pr_trace_msg("response", 9, "flushing error response list for '%s'",
775           (char *) cmd->argv[0]);
776         pr_response_flush(&resp_err_list);
777       }
778 
779       errno = xerrno;
780     }
781   }
782 
783   /* Restore any previous pool to the Response API. */
784   pr_response_set_pool(resp_pool);
785 
786   errno = xerrno;
787   return success;
788 }
789 
pr_cmd_dispatch(cmd_rec * cmd)790 int pr_cmd_dispatch(cmd_rec *cmd) {
791   return pr_cmd_dispatch_phase(cmd, 0,
792     PR_CMD_DISPATCH_FL_SEND_RESPONSE|PR_CMD_DISPATCH_FL_CLEAR_RESPONSE);
793 }
794 
make_ftp_cmd(pool * p,char * buf,size_t buflen,int flags)795 static cmd_rec *make_ftp_cmd(pool *p, char *buf, size_t buflen, int flags) {
796   register unsigned int i, j;
797   char *arg, *ptr, *wrd;
798   size_t arg_len;
799   cmd_rec *cmd;
800   pool *subpool;
801   array_header *tarr;
802   int have_crnul = FALSE, str_flags = PR_STR_FL_PRESERVE_COMMENTS|flags;
803 
804   /* Be pedantic (and RFC-compliant) by not allowing leading whitespace
805    * in an issued FTP command.  Will this cause troubles with many clients?
806    */
807   if (PR_ISSPACE(buf[0])) {
808     pr_trace_msg("ctrl", 5,
809       "command '%s' has illegal leading whitespace, rejecting", buf);
810     errno = EINVAL;
811     return NULL;
812   }
813 
814   ptr = buf;
815   wrd = pr_str_get_word(&ptr, str_flags);
816   if (wrd == NULL) {
817     /* Nothing there...bail out. */
818     pr_trace_msg("ctrl", 5, "command '%s' is empty, ignoring", buf);
819     errno = ENOENT;
820     return NULL;
821   }
822 
823   subpool = make_sub_pool(p);
824   pr_pool_tag(subpool, "make_ftp_cmd pool");
825   cmd = pcalloc(subpool, sizeof(cmd_rec));
826   cmd->pool = subpool;
827   cmd->tmp_pool = NULL;
828   cmd->stash_index = -1;
829   cmd->stash_hash = 0;
830 
831   tarr = make_array(cmd->pool, 2, sizeof(char *));
832 
833   *((char **) push_array(tarr)) = pstrdup(cmd->pool, wrd);
834   cmd->argc++;
835 
836   /* Make a copy of the command argument; we need to scan through it,
837    * looking for any CR+NUL sequences, per RFC 2460, Section 3.1.
838    *
839    * Note for future readers that this scanning may cause problems for
840    * commands such as ADAT, ENC, and MIC.  Per RFC 2228, the arguments for
841    * these commands are base64-encoded Telnet strings, thus there is no
842    * chance of them containing CRNUL sequences.  Any modules which implement
843    * the translating of those arguments, e.g. mod_gss, will need to ensure
844    * it does the proper handling of CRNUL sequences itself.
845    */
846   arg_len = buflen - strlen(wrd);
847   arg = pcalloc(cmd->pool, arg_len + 1);
848 
849   for (i = 0, j = 0; i < arg_len; i++) {
850     pr_signals_handle();
851     if (i > 1 &&
852         ptr[i] == '\0' &&
853         ptr[i-1] == '\r') {
854 
855       /* Strip out the NUL by simply not copying it into the new buffer. */
856       have_crnul = TRUE;
857     } else {
858       arg[j++] = ptr[i];
859     }
860   }
861 
862   cmd->arg = arg;
863 
864   if (have_crnul) {
865     char *dup_arg;
866 
867     /* Now make a copy of the stripped argument; this is what we need to
868      * tokenize into words, for further command dispatching/processing.
869      */
870     dup_arg = pstrdup(cmd->pool, arg);
871     ptr = dup_arg;
872   }
873 
874   while ((wrd = pr_str_get_word(&ptr, str_flags)) != NULL) {
875     pr_signals_handle();
876     *((char **) push_array(tarr)) = pstrdup(cmd->pool, wrd);
877     cmd->argc++;
878   }
879 
880   *((char **) push_array(tarr)) = NULL;
881   cmd->argv = tarr->elts;
882   pr_pool_tag(cmd->pool, cmd->argv[0]);
883 
884   /* This table will not contain that many entries, so a low number
885    * of chains should suffice.
886    */
887   cmd->notes = pr_table_nalloc(cmd->pool, 0, 8);
888 
889   return cmd;
890 }
891 
cmd_loop(server_rec * server,conn_t * c)892 static void cmd_loop(server_rec *server, conn_t *c) {
893 
894   while (TRUE) {
895     int res = 0;
896     cmd_rec *cmd = NULL;
897 
898     pr_signals_handle();
899 
900     res = pr_cmd_read(&cmd);
901     if (res < 0) {
902       if (PR_NETIO_ERRNO(session.c->instrm) == EINTR) {
903         /* Simple interrupted syscall */
904         continue;
905       }
906 
907 #ifndef PR_DEVEL_NO_DAEMON
908       /* Otherwise, EOF */
909       pr_session_disconnect(NULL, PR_SESS_DISCONNECT_CLIENT_EOF, NULL);
910 #else
911       return;
912 #endif /* PR_DEVEL_NO_DAEMON */
913     }
914 
915     /* Data received, reset idle timer */
916     if (pr_data_get_timeout(PR_DATA_TIMEOUT_IDLE) > 0) {
917       pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
918     }
919 
920     if (cmd != NULL) {
921       /* Detect known commands for other protocols; if found, drop the
922        * connection, lest we be used as part of an attack on a different
923        * protocol server (Bug#4143).
924        */
925       if (cmd->is_ftp == FALSE) {
926         pr_log_pri(PR_LOG_WARNING,
927           "client sent %s command '%s', disconnecting", cmd->protocol,
928           (char *) cmd->argv[0]);
929         pr_event_generate("core.bad-protocol", cmd);
930         pr_session_disconnect(NULL, PR_SESS_DISCONNECT_BAD_PROTOCOL,
931           cmd->protocol);
932       }
933 
934       pr_cmd_dispatch(cmd);
935       destroy_pool(cmd->pool);
936       session.curr_cmd = NULL;
937       session.curr_cmd_id = 0;
938       session.curr_cmd_rec = NULL;
939 
940     } else {
941       pr_event_generate("core.invalid-command", NULL);
942       pr_response_send(R_500, _("Invalid command: try being more creative"));
943     }
944 
945     /* Release any working memory allocated in inet */
946     pr_inet_clear();
947   }
948 }
949 
restart_daemon(void * d1,void * d2,void * d3,void * d4)950 void restart_daemon(void *d1, void *d2, void *d3, void *d4) {
951   if (is_master && mpid) {
952     int maxfd;
953     fd_set childfds;
954     struct timeval restart_start, restart_finish;
955     long restart_elapsed = 0;
956 
957     pr_log_pri(PR_LOG_NOTICE, "received SIGHUP -- master server reparsing "
958       "configuration file");
959 
960     gettimeofday(&restart_start, NULL);
961 
962     /* Make sure none of our children haven't completed start up */
963     FD_ZERO(&childfds);
964     maxfd = -1;
965 
966     maxfd = semaphore_fds(&childfds, maxfd);
967     if (maxfd > -1) {
968       pr_log_pri(PR_LOG_NOTICE, "waiting for child processes to complete "
969         "initialization");
970 
971       while (maxfd != -1) {
972 	int i;
973 
974 	i = select(maxfd + 1, &childfds, NULL, NULL, NULL);
975 
976         if (i > 0) {
977           pr_child_t *ch;
978 
979           for (ch = child_get(NULL); ch; ch = child_get(ch)) {
980             if (ch->ch_pipefd != -1 &&
981                FD_ISSET(ch->ch_pipefd, &childfds)) {
982               (void) close(ch->ch_pipefd);
983               ch->ch_pipefd = -1;
984             }
985           }
986         }
987 
988 	FD_ZERO(&childfds);
989         maxfd = -1;
990 	maxfd = semaphore_fds(&childfds, maxfd);
991       }
992     }
993 
994     free_bindings();
995 
996     /* Run through the list of registered restart callbacks. */
997     pr_event_generate("core.restart", NULL);
998 
999     init_log();
1000     init_netaddr();
1001     init_class();
1002     init_config();
1003     init_dirtree();
1004 
1005 #ifdef PR_USE_NLS
1006     encode_free();
1007 #endif /* PR_USE_NLS */
1008 
1009     pr_netaddr_clear_cache();
1010 
1011     pr_parser_prepare(NULL, NULL);
1012 
1013     pr_event_generate("core.preparse", NULL);
1014 
1015     PRIVS_ROOT
1016     if (pr_parser_parse_file(NULL, config_filename, NULL, 0) < 0) {
1017       int xerrno = errno;
1018 
1019       PRIVS_RELINQUISH
1020 
1021       /* Note: EPERM is used to indicate the presence of unrecognized
1022        * configuration directives in the parsed file(s).
1023        */
1024       if (xerrno != EPERM) {
1025         pr_log_pri(PR_LOG_WARNING,
1026           "fatal: unable to read configuration file '%s': %s", config_filename,
1027           strerror(xerrno));
1028       }
1029 
1030       pr_session_end(0);
1031     }
1032     PRIVS_RELINQUISH
1033 
1034     if (pr_parser_cleanup() < 0) {
1035       pr_log_pri(PR_LOG_WARNING,
1036         "fatal: error processing configuration file '%s': "
1037         "unclosed configuration section", config_filename);
1038       pr_session_end(0);
1039     }
1040 
1041 #ifdef PR_USE_NLS
1042     encode_init();
1043 #endif /* PR_USE_NLS */
1044 
1045     /* After configuration is complete, make sure that passwd, group
1046      * aren't held open (unnecessary fds for master daemon)
1047      */
1048     endpwent();
1049     endgrent();
1050 
1051     if (fixup_servers(server_list) < 0) {
1052       pr_log_pri(PR_LOG_WARNING,
1053         "fatal: error processing configuration file '%s'", config_filename);
1054       pr_session_end(0);
1055     }
1056 
1057     pr_event_generate("core.postparse", NULL);
1058 
1059     /* Recreate the listen connection.  Can an inetd-spawned server accept
1060      * and process HUP?
1061      */
1062     init_bindings();
1063 
1064     gettimeofday(&restart_finish, NULL);
1065 
1066     restart_elapsed = ((restart_finish.tv_sec - restart_start.tv_sec) * 1000L) +
1067       ((restart_finish.tv_usec - restart_start.tv_usec) / 1000L);
1068     pr_trace_msg("config", 12, "restart took %ld millisecs", restart_elapsed);
1069 
1070   } else {
1071 
1072     /* Child process -- cannot restart, log error */
1073     pr_log_pri(PR_LOG_ERR, "received SIGHUP, cannot restart child process");
1074   }
1075 }
1076 
set_server_privs(void)1077 static void set_server_privs(void) {
1078   uid_t server_uid, current_euid = geteuid();
1079   gid_t server_gid, current_egid = getegid();
1080   unsigned char switch_server_id = FALSE;
1081 
1082   uid_t *uid = get_param_ptr(main_server->conf, "UserID", FALSE);
1083   gid_t *gid =  get_param_ptr(main_server->conf, "GroupID", FALSE);
1084 
1085   if (uid) {
1086     server_uid = *uid;
1087     switch_server_id = TRUE;
1088 
1089   } else
1090     server_uid = current_euid;
1091 
1092   if (gid) {
1093     server_gid = *gid;
1094     switch_server_id = TRUE;
1095 
1096   } else
1097     server_gid = current_egid;
1098 
1099   if (switch_server_id) {
1100     PRIVS_ROOT
1101 
1102     /* Note: will it be necessary to double check this switch, as is done
1103      * in elsewhere in this file?
1104      */
1105     PRIVS_SETUP(server_uid, server_gid);
1106   }
1107 }
1108 
fork_server(int fd,conn_t * l,unsigned char no_fork)1109 static void fork_server(int fd, conn_t *l, unsigned char no_fork) {
1110   conn_t *conn = NULL;
1111   int i, rev;
1112   int semfds[2] = { -1, -1 };
1113   int xerrno = 0;
1114 
1115 #ifndef PR_DEVEL_NO_FORK
1116   pid_t pid;
1117   sigset_t sig_set;
1118 
1119   if (no_fork == FALSE) {
1120 
1121     /* A race condition exists on heavily loaded servers where the parent
1122      * catches SIGHUP and attempts to close/re-open the main listening
1123      * socket(s), however the children haven't finished closing them
1124      * (EADDRINUSE).  We use a semaphore pipe here to flag the parent once
1125      * the child has closed all former listening sockets.
1126      */
1127 
1128     if (pipe(semfds) == -1) {
1129       pr_log_pri(PR_LOG_ALERT, "pipe(2) failed: %s", strerror(errno));
1130       (void) close(fd);
1131       return;
1132     }
1133 
1134     /* Need to make sure the child (writer) end of the pipe isn't
1135      * < 2 (stdio/stdout/stderr) as this will cause problems later.
1136      */
1137     semfds[1] = pr_fs_get_usable_fd(semfds[1]);
1138 
1139     /* Make sure we set the close-on-exec flag for the parent's read side
1140      * of the pipe.
1141      */
1142     (void) fcntl(semfds[0], F_SETFD, FD_CLOEXEC);
1143 
1144     /* We block SIGCHLD to prevent a race condition if the child
1145      * dies before we can record it's pid.  Also block SIGTERM to
1146      * prevent sig_terminate() from examining the child list
1147      */
1148 
1149     sigemptyset(&sig_set);
1150     sigaddset(&sig_set, SIGTERM);
1151     sigaddset(&sig_set, SIGCHLD);
1152     sigaddset(&sig_set, SIGUSR1);
1153     sigaddset(&sig_set, SIGUSR2);
1154 
1155     if (sigprocmask(SIG_BLOCK, &sig_set, NULL) < 0) {
1156       pr_log_pri(PR_LOG_NOTICE,
1157         "unable to block signal set: %s", strerror(errno));
1158     }
1159 
1160     pid = fork();
1161     xerrno = errno;
1162 
1163     switch (pid) {
1164 
1165     case 0: /* child */
1166       /* No longer the master process. */
1167       is_master = FALSE;
1168       if (sigprocmask(SIG_UNBLOCK, &sig_set, NULL) < 0) {
1169         pr_log_pri(PR_LOG_NOTICE,
1170           "unable to unblock signal set: %s", strerror(errno));
1171       }
1172 
1173       /* No longer need the read side of the semaphore pipe. */
1174       (void) close(semfds[0]);
1175       break;
1176 
1177     case -1:
1178       if (sigprocmask(SIG_UNBLOCK, &sig_set, NULL) < 0) {
1179         pr_log_pri(PR_LOG_NOTICE,
1180           "unable to unblock signal set: %s", strerror(errno));
1181       }
1182 
1183       pr_log_pri(PR_LOG_ALERT, "unable to fork(): %s", strerror(xerrno));
1184 
1185       /* The parent doesn't need the socket open. */
1186       (void) close(fd);
1187       (void) close(semfds[0]);
1188       (void) close(semfds[1]);
1189 
1190       return;
1191 
1192     default: /* parent */
1193       /* The parent doesn't need the socket open */
1194       (void) close(fd);
1195 
1196       child_add(pid, semfds[0]);
1197       (void) close(semfds[1]);
1198 
1199       /* Unblock the signals now as sig_child() will catch
1200        * an "immediate" death and remove the pid from the children list
1201        */
1202       if (sigprocmask(SIG_UNBLOCK, &sig_set, NULL) < 0) {
1203         pr_log_pri(PR_LOG_NOTICE,
1204           "unable to unblock signal set: %s", strerror(errno));
1205       }
1206 
1207       return;
1208     }
1209   }
1210 
1211   session.pid = getpid();
1212 
1213   /* No longer need any listening fds. */
1214   pr_ipbind_close_listeners();
1215 
1216   /* There would appear to be no useful purpose behind setting the process
1217    * group of the newly forked child.  In daemon/inetd mode, we should have no
1218    * controlling tty and either have the process group of the parent or of
1219    * inetd.  In non-daemon mode (-n), doing this may cause SIGTTOU to be
1220    * raised on output to the terminal (stderr logging).
1221    *
1222    * #ifdef HAVE_SETPGID
1223    *   setpgid(0,getpid());
1224    * #else
1225    * # ifdef SETPGRP_VOID
1226    *   setpgrp();
1227    * # else
1228    *   setpgrp(0,getpid());
1229    * # endif
1230    * #endif
1231    *
1232    */
1233 
1234   /* Reseed pseudo-randoms */
1235   pr_random_init();
1236 
1237 #endif /* PR_DEVEL_NO_FORK */
1238 
1239   /* Child is running here */
1240   if (signal(SIGUSR1, pr_signals_handle_disconnect) == SIG_ERR) {
1241     pr_log_pri(PR_LOG_NOTICE,
1242       "unable to install SIGUSR1 (signal %d) handler: %s", SIGUSR1,
1243       strerror(errno));
1244   }
1245 
1246   if (signal(SIGUSR2, pr_signals_handle_event) == SIG_ERR) {
1247     pr_log_pri(PR_LOG_NOTICE,
1248       "unable to install SIGUSR2 (signal %d) handler: %s", SIGUSR2,
1249       strerror(errno));
1250   }
1251 
1252   if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
1253     pr_log_pri(PR_LOG_NOTICE,
1254       "unable to install SIGCHLD (signal %d) handler: %s", SIGCHLD,
1255       strerror(errno));
1256   }
1257 
1258   if (signal(SIGHUP, SIG_IGN) == SIG_ERR) {
1259     pr_log_pri(PR_LOG_NOTICE,
1260       "unable to install SIGHUP (signal %d) handler: %s", SIGHUP,
1261       strerror(errno));
1262   }
1263 
1264   /* From this point on, syslog stays open. We close it first so that the
1265    * logger will pick up our new PID.
1266    *
1267    * We have to delay calling log_opensyslog() until after pr_inet_openrw()
1268    * is called, otherwise the potential exists for the syslog FD to
1269    * be overwritten and the user to see logging information.
1270    *
1271    * This isn't that big of a deal because the logging functions will
1272    * just open it dynamically if they need to.
1273    */
1274   log_closesyslog();
1275 
1276   /* Specifically DO NOT perform reverse DNS at this point, to alleviate
1277    * the race condition mentioned above.  Instead we do it after closing
1278    * all former listening sockets.
1279    */
1280   conn = pr_inet_openrw(permanent_pool, l, NULL, PR_NETIO_STRM_CTRL, fd,
1281     STDIN_FILENO, STDOUT_FILENO, FALSE);
1282 
1283   /* Capture errno here, if necessary. */
1284   if (conn == NULL) {
1285     xerrno = errno;
1286   }
1287 
1288   /* Now do the permanent syslog open
1289    */
1290   pr_signals_block();
1291   PRIVS_ROOT
1292 
1293   log_opensyslog(NULL);
1294 
1295   PRIVS_RELINQUISH
1296   pr_signals_unblock();
1297 
1298   if (conn == NULL) {
1299     /* There are some errors, e.g. ENOTCONN ("Transport endpoint is not
1300      * connected") which can easily happen, as during scans/TCP
1301      * probes/healthchecks, commonly done by load balancers, firewalls, and
1302      * other clients.  By the time proftpd reaches the point of looking up
1303      * the peer data for that connection, the client has disconnected.
1304      *
1305      * These are normal errors, and thus should not be logged as fatal
1306      * conditions.
1307      */
1308     if (xerrno == ENOTCONN ||
1309         xerrno == ECONNABORTED ||
1310         xerrno == ECONNRESET) {
1311       pr_log_pri(PR_LOG_DEBUG, "unable to open incoming connection: %s",
1312         strerror(xerrno));
1313 
1314     } else {
1315       pr_log_pri(PR_LOG_ERR, "fatal: unable to open incoming connection: %s",
1316         strerror(xerrno));
1317     }
1318 
1319     exit(1);
1320   }
1321 
1322   pr_gettimeofday_millis(&session.connect_time_ms);
1323   pr_event_generate("core.connect", conn);
1324 
1325   /* Find the server for this connection. */
1326   main_server = pr_ipbind_get_server(conn->local_addr, conn->local_port);
1327 
1328   /* Make sure we allocate a session pool, even if this connection will
1329    * dropped soon.
1330    */
1331   session.pool = make_sub_pool(permanent_pool);
1332   pr_pool_tag(session.pool, "Session Pool");
1333 
1334   session.c = conn;
1335   session.data_port = conn->remote_port - 1;
1336   session.sf_flags = 0;
1337   session.sp_flags = 0;
1338   session.proc_prefix = "(connecting)";
1339 
1340   /* If no server is configured to handle the addr the user is connected to,
1341    * drop them.
1342    */
1343   if (main_server == NULL) {
1344     pr_log_debug(DEBUG2, "No server configuration found for IP address %s",
1345       pr_netaddr_get_ipstr(conn->local_addr));
1346     pr_log_debug(DEBUG2, "Use the DefaultServer directive to designate "
1347       "a default server configuration to handle requests like this");
1348 
1349     pr_response_send(R_500,
1350       _("Sorry, no server available to handle request on %s"),
1351       pr_netaddr_get_dnsstr(conn->local_addr));
1352     exit(0);
1353   }
1354 
1355   pr_inet_set_proto_opts(permanent_pool, conn, 0, 1, IPTOS_LOWDELAY, 0);
1356 
1357   /* Close the write side of the semaphore pipe to tell the parent
1358    * we are all grown up and have finished housekeeping (closing
1359    * former listen sockets).
1360    */
1361   close(semfds[1]);
1362 
1363   /* Now perform reverse DNS lookups. */
1364   if (ServerUseReverseDNS) {
1365     rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
1366 
1367     if (conn->remote_addr)
1368       conn->remote_name = pr_netaddr_get_dnsstr(conn->remote_addr);
1369 
1370     pr_netaddr_set_reverse_dns(rev);
1371   }
1372 
1373   pr_netaddr_set_sess_addrs();
1374 
1375   /* Check and see if we are shutting down. */
1376   if (shutting_down) {
1377     time_t now;
1378 
1379     time(&now);
1380     if (!deny || deny <= now) {
1381       pool *tmp_pool;
1382       config_rec *c = NULL;
1383       const char *reason = NULL, *serveraddress;
1384 
1385       serveraddress = (session.c && session.c->local_addr) ?
1386         pr_netaddr_get_ipstr(session.c->local_addr) :
1387         main_server->ServerAddress;
1388 
1389       c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress",
1390         FALSE);
1391       if (c != NULL) {
1392         pr_netaddr_t *masq_addr = NULL;
1393 
1394         if (c->argv[0] != NULL) {
1395           masq_addr = c->argv[0];
1396         }
1397 
1398         if (masq_addr != NULL) {
1399           serveraddress = pr_netaddr_get_ipstr(masq_addr);
1400         }
1401       }
1402 
1403       tmp_pool = make_sub_pool(permanent_pool);
1404       pr_pool_tag(tmp_pool, "shutmsg check pool");
1405 
1406       reason = sreplace(tmp_pool, shutmsg,
1407                    "%s", pstrdup(tmp_pool, pr_strtime3(tmp_pool, shut, FALSE)),
1408                    "%r", pstrdup(tmp_pool, pr_strtime3(tmp_pool, deny, FALSE)),
1409                    "%d", pstrdup(tmp_pool, pr_strtime3(tmp_pool, disc, FALSE)),
1410 		   "%C", (session.cwd[0] ? session.cwd : "(none)"),
1411 		   "%L", serveraddress,
1412 		   "%R", (session.c && session.c->remote_name ?
1413                          session.c->remote_name : "(unknown)"),
1414 		   "%T", pstrdup(tmp_pool, pr_strtime3(tmp_pool, now, FALSE)),
1415 		   "%U", "NONE",
1416 		   "%V", main_server->ServerName,
1417                    NULL );
1418 
1419       pr_log_auth(PR_LOG_NOTICE, "connection refused (%s) from %s [%s]",
1420         reason, session.c->remote_name,
1421         pr_netaddr_get_ipstr(session.c->remote_addr));
1422       pr_response_send(R_500,
1423         _("FTP server shut down (%s) -- please try again later"), reason);
1424 
1425       destroy_pool(tmp_pool);
1426       exit(0);
1427     }
1428   }
1429 
1430   if (main_server->listen) {
1431     if (main_server->listen->listen_fd == conn->rfd ||
1432         main_server->listen->listen_fd == conn->wfd) {
1433       main_server->listen->listen_fd = -1;
1434     }
1435 
1436     main_server->listen = NULL;
1437   }
1438 
1439   /* Set the ID/privs for the User/Group in this server */
1440   set_server_privs();
1441 
1442   /* Find the class for this session. */
1443   session.conn_class = pr_class_match_addr(session.c->remote_addr);
1444   if (session.conn_class != NULL) {
1445     pr_log_debug(DEBUG2, "session requested from client in '%s' class",
1446       session.conn_class->cls_name);
1447 
1448   } else {
1449     pr_log_debug(DEBUG5, "session requested from client in unknown class");
1450   }
1451 
1452   /* Check config tree for <Limit LOGIN> directives.  Do not perform
1453    * this check until after the class of the session has been determined,
1454    * in order to properly handle any AllowClass/DenyClass directives
1455    * within the <Limit> section.
1456    */
1457   if (!login_check_limits(main_server->conf, TRUE, FALSE, &i)) {
1458     pr_log_pri(PR_LOG_NOTICE, "Connection from %s [%s] denied",
1459       session.c->remote_name,
1460       pr_netaddr_get_ipstr(session.c->remote_addr));
1461 
1462     /* XXX Send DisplayConnect here? No chroot to worry about; modules have
1463      * NOT been initialized, so generating an event would not work as
1464      * expected.
1465      */
1466 
1467     pr_session_disconnect(NULL, PR_SESS_DISCONNECT_CONFIG_ACL,
1468       "Blocked by <Limit LOGIN>");
1469   }
1470 
1471   /* Create a table for modules to use. */
1472   session.notes = pr_table_alloc(session.pool, 0);
1473   if (session.notes == NULL) {
1474     pr_log_debug(DEBUG3, "error creating session.notes table: %s",
1475       strerror(errno));
1476   }
1477 
1478   /* Prepare the Timers API. */
1479   timers_init();
1480 
1481   /* Inform all the modules that we are now a child */
1482   pr_log_debug(DEBUG7, "performing module session initializations");
1483   if (modules_session_init() < 0) {
1484     pr_session_disconnect(NULL, PR_SESS_DISCONNECT_SESSION_INIT_FAILED, NULL);
1485   }
1486 
1487   pr_log_debug(DEBUG4, "connected - local  : %s:%d",
1488     pr_netaddr_get_ipstr(session.c->local_addr), session.c->local_port);
1489   pr_log_debug(DEBUG4, "connected - remote : %s:%d",
1490     pr_netaddr_get_ipstr(session.c->remote_addr), session.c->remote_port);
1491 
1492   pr_proctitle_set("connected: %s (%s:%d)",
1493     session.c->remote_name ? session.c->remote_name : "?",
1494     session.c->remote_addr ? pr_netaddr_get_ipstr(session.c->remote_addr) : "?",
1495     session.c->remote_port ? session.c->remote_port : 0);
1496 
1497   pr_log_pri(PR_LOG_INFO, "%s session opened.",
1498     pr_session_get_protocol(PR_SESS_PROTO_FL_LOGOUT));
1499 
1500   /* Make sure we can receive OOB data */
1501   pr_inet_set_async(session.pool, session.c);
1502 
1503   pr_session_send_banner(main_server,
1504     PR_DISPLAY_FL_NO_EOM|PR_DISPLAY_FL_SEND_NOW);
1505 
1506   cmd_handler(main_server, conn);
1507 
1508 #ifdef PR_DEVEL_NO_DAEMON
1509   /* Cleanup */
1510   pr_session_end(PR_SESS_END_FL_NOEXIT);
1511   main_server = NULL;
1512   free_pools();
1513   pr_proctitle_free();
1514 #endif /* PR_DEVEL_NO_DAEMON */
1515 }
1516 
disc_children(void)1517 static void disc_children(void) {
1518 
1519   if (disc && disc <= time(NULL) && child_count()) {
1520     sigset_t sig_set;
1521 
1522     sigemptyset(&sig_set);
1523     sigaddset(&sig_set, SIGTERM);
1524     sigaddset(&sig_set, SIGCHLD);
1525     sigaddset(&sig_set, SIGUSR1);
1526     sigaddset(&sig_set, SIGUSR2);
1527 
1528     if (sigprocmask(SIG_BLOCK, &sig_set, NULL) < 0) {
1529       pr_log_pri(PR_LOG_NOTICE,
1530         "unable to block signal set: %s", strerror(errno));
1531     }
1532 
1533     PRIVS_ROOT
1534     child_signal(SIGUSR1);
1535     PRIVS_RELINQUISH
1536 
1537     if (sigprocmask(SIG_UNBLOCK, &sig_set, NULL) < 0) {
1538       pr_log_pri(PR_LOG_NOTICE,
1539         "unable to unblock signal set: %s", strerror(errno));
1540     }
1541   }
1542 }
1543 
daemon_loop(void)1544 static void daemon_loop(void) {
1545   fd_set listenfds;
1546   conn_t *listen_conn;
1547   int i, err_count = 0, fd, xerrno = 0;
1548   unsigned long nconnects = 0UL;
1549   time_t last_error;
1550   struct timeval tv;
1551   static int running = 0;
1552 
1553   pr_proctitle_set("(accepting connections)");
1554 
1555   time(&last_error);
1556 
1557   while (TRUE) {
1558     int maxfd;
1559 
1560     run_schedule();
1561 
1562     FD_ZERO(&listenfds);
1563     maxfd = pr_ipbind_listen(&listenfds);
1564 
1565     /* Monitor children pipes */
1566     maxfd = semaphore_fds(&listenfds, maxfd);
1567 
1568     /* Check for ftp shutdown message file */
1569     switch (check_shutmsg(permanent_pool, PR_SHUTMSG_PATH, &shut, &deny,
1570         &disc, shutmsg, sizeof(shutmsg))) {
1571       case 1:
1572         if (!shutting_down) {
1573           disc_children();
1574         }
1575         shutting_down = TRUE;
1576         break;
1577 
1578       default:
1579         shutting_down = FALSE;
1580         deny = disc = (time_t) 0;
1581         break;
1582     }
1583 
1584     if (shutting_down) {
1585       tv.tv_sec = 5L;
1586       tv.tv_usec = 0L;
1587 
1588     } else {
1589 
1590       tv.tv_sec = PR_TUNABLE_SELECT_TIMEOUT;
1591       tv.tv_usec = 0L;
1592     }
1593 
1594     /* If running (a flag signaling whether proftpd is just starting up)
1595      * AND shutting_down (a flag signalling the present of /etc/shutmsg) are
1596      * true, then log an error stating this -- but don't stop the server.
1597      */
1598     if (shutting_down && !running) {
1599 
1600       /* Check the value of the deny time_t struct w/ the current time.
1601        * If the deny time has passed, log that all incoming connections
1602        * will be refused.  If not, note the date at which they will be
1603        * refused in the future.
1604        */
1605       time_t now = time(NULL);
1606 
1607       if (difftime(deny, now) < 0.0) {
1608         pr_log_pri(PR_LOG_WARNING, PR_SHUTMSG_PATH
1609           " present: all incoming connections will be refused");
1610 
1611       } else {
1612 #if defined(HAVE_CTIME_R)
1613         char deny_ts[32];
1614 
1615         memset(deny_ts, '\0', sizeof(deny_ts));
1616         (void) ctime_r(&deny, deny_ts);
1617 #else
1618         char *deny_ts = NULL;
1619         deny_ts = ctime(&deny);
1620 #endif /* HAVE_CTIME_R */
1621 
1622         pr_log_pri(PR_LOG_NOTICE,
1623           PR_SHUTMSG_PATH " present: incoming connections "
1624           "will be denied starting %s", CHOP(deny_ts));
1625       }
1626     }
1627 
1628     running = 1;
1629     xerrno = errno = 0;
1630 
1631     PR_DEVEL_CLOCK(i = select(maxfd + 1, &listenfds, NULL, NULL, &tv));
1632     if (i < 0) {
1633       xerrno = errno;
1634     }
1635 
1636     if (i == -1 &&
1637         xerrno == EINTR) {
1638       errno = xerrno;
1639       pr_signals_handle();
1640 
1641       /* We handled our signal; clear errno. */
1642       xerrno = errno = 0;
1643       continue;
1644     }
1645 
1646     if (have_dead_child) {
1647       sigset_t sig_set;
1648 
1649       sigemptyset(&sig_set);
1650       sigaddset(&sig_set, SIGCHLD);
1651       sigaddset(&sig_set, SIGTERM);
1652       pr_alarms_block();
1653       if (sigprocmask(SIG_BLOCK, &sig_set, NULL) < 0) {
1654         pr_log_pri(PR_LOG_NOTICE,
1655           "unable to block signal set: %s", strerror(errno));
1656       }
1657 
1658       have_dead_child = FALSE;
1659       child_update();
1660 
1661       if (sigprocmask(SIG_UNBLOCK, &sig_set, NULL) < 0) {
1662         pr_log_pri(PR_LOG_NOTICE,
1663           "unable to unblock signal set: %s", strerror(errno));
1664       }
1665 
1666       pr_alarms_unblock();
1667     }
1668 
1669     if (i == -1) {
1670       time_t this_error;
1671 
1672       time(&this_error);
1673 
1674       if ((this_error - last_error) <= 5 && err_count++ > 10) {
1675         pr_log_pri(PR_LOG_ERR, "fatal: select(2) failing repeatedly, shutting "
1676           "down");
1677         exit(1);
1678 
1679       } else if ((this_error - last_error) > 5) {
1680         last_error = this_error;
1681         err_count = 0;
1682       }
1683 
1684       pr_log_pri(PR_LOG_WARNING, "select(2) failed in daemon_loop(): %s",
1685         strerror(xerrno));
1686     }
1687 
1688     if (i == 0) {
1689       continue;
1690     }
1691 
1692     /* Reset the connection counter.  Take into account this current
1693      * connection, which does not (yet) have an entry in the child list.
1694      */
1695     nconnects = 1UL;
1696 
1697     /* See if child semaphore pipes have signaled */
1698     if (child_count()) {
1699       pr_child_t *ch;
1700       time_t now = time(NULL);
1701 
1702       for (ch = child_get(NULL); ch; ch = child_get(ch)) {
1703 	if (ch->ch_pipefd != -1 &&
1704             FD_ISSET(ch->ch_pipefd, &listenfds)) {
1705 	  (void) close(ch->ch_pipefd);
1706 	  ch->ch_pipefd = -1;
1707 	}
1708 
1709         /* While we're looking, tally up the number of children forked in
1710          * the past interval.
1711          */
1712         if (ch->ch_when >= (time_t) (now - (long) max_connect_interval)) {
1713           nconnects++;
1714         }
1715       }
1716     }
1717 
1718     pr_signals_handle();
1719 
1720     if (i < 0) {
1721       continue;
1722     }
1723 
1724     /* Accept the connection. */
1725     listen_conn = pr_ipbind_accept_conn(&listenfds, &fd);
1726 
1727     /* Fork off servers to handle each connection our job is to get back to
1728      * answering connections ASAP, so leave the work of determining which
1729      * server the connection is for to our child.
1730      */
1731 
1732     if (listen_conn != NULL) {
1733 
1734       /* Check for exceeded MaxInstances. */
1735       if (ServerMaxInstances > 0 &&
1736           child_count() >= ServerMaxInstances) {
1737         pr_event_generate("core.max-instances", NULL);
1738 
1739         pr_log_pri(PR_LOG_WARNING,
1740           "MaxInstances (%lu) reached, new connection denied",
1741           ServerMaxInstances);
1742         close(fd);
1743 
1744       /* Check for exceeded MaxConnectionRate. */
1745       } else if (max_connects && (nconnects > max_connects)) {
1746         pr_event_generate("core.max-connection-rate", NULL);
1747 
1748         pr_log_pri(PR_LOG_WARNING,
1749           "MaxConnectionRate (%lu/%u secs) reached, new connection denied",
1750           max_connects, max_connect_interval);
1751         close(fd);
1752 
1753       /* Fork off a child to handle the connection. */
1754       } else {
1755         PR_DEVEL_CLOCK(fork_server(fd, listen_conn, no_forking));
1756       }
1757     }
1758 #ifdef PR_DEVEL_NO_DAEMON
1759     /* Do not continue the while() loop here if not daemonizing. */
1760     break;
1761 #endif /* PR_DEVEL_NO_DAEMON */
1762   }
1763 }
1764 
daemonize(void)1765 static void daemonize(void) {
1766 #ifndef HAVE_SETSID
1767   int ttyfd;
1768 #endif
1769 
1770   /* Fork off and have parent exit.
1771    */
1772   switch (fork()) {
1773     case -1:
1774       perror("fork(2) error");
1775       exit(1);
1776 
1777     case 0:
1778       break;
1779 
1780     default:
1781       exit(0);
1782   }
1783 
1784 #ifdef HAVE_SETSID
1785   /* setsid() is the preferred way to disassociate from the
1786    * controlling terminal
1787    */
1788   setsid();
1789 #else
1790   /* Open /dev/tty to access our controlling tty (if any) */
1791   if ((ttyfd = open("/dev/tty", O_RDWR)) != -1) {
1792     if (ioctl(ttyfd, TIOCNOTTY, NULL) == -1) {
1793       perror("ioctl");
1794       exit(1);
1795     }
1796 
1797     close(ttyfd);
1798   }
1799 #endif /* HAVE_SETSID */
1800 
1801   /* Close the three big boys */
1802   close(fileno(stdin));
1803   close(fileno(stdout));
1804   close(fileno(stderr));
1805 
1806   /* Portable way to prevent re-acquiring a tty in the future */
1807 
1808 #ifdef HAVE_SETPGID
1809   setpgid(0, getpid());
1810 #else
1811 # ifdef SETPGRP_VOID
1812   setpgrp();
1813 # else
1814   setpgrp(0, getpid());
1815 # endif
1816 #endif
1817 
1818   /* Reset the cached "master PID" value to that of the daemon process;
1819    * there are places in the code which check this value to see if they
1820    * are the daemon process, e.g. at shutdown.
1821    */
1822   mpid = getpid();
1823 
1824   pr_fsio_chdir("/", 0);
1825 }
1826 
inetd_main(void)1827 static void inetd_main(void) {
1828   int res = 0;
1829 
1830   /* Make sure the scoreboard file exists. */
1831   PRIVS_ROOT
1832   res = pr_open_scoreboard(O_RDWR);
1833   if (res < 0) {
1834     PRIVS_RELINQUISH
1835 
1836     switch (res) {
1837       case PR_SCORE_ERR_BAD_MAGIC:
1838         pr_log_pri(PR_LOG_ERR, "error opening scoreboard: bad/corrupted file");
1839         return;
1840 
1841       case PR_SCORE_ERR_OLDER_VERSION:
1842       case PR_SCORE_ERR_NEWER_VERSION:
1843         pr_log_pri(PR_LOG_ERR, "error opening scoreboard: wrong version, "
1844           "writing new scoreboard");
1845 
1846         /* Delete the scoreboard, then open it again. */
1847         PRIVS_ROOT
1848         pr_delete_scoreboard();
1849         if (pr_open_scoreboard(O_RDWR) < 0) {
1850           int xerrno = errno;
1851 
1852           PRIVS_RELINQUISH
1853           pr_log_pri(PR_LOG_ERR, "error opening scoreboard: %s",
1854             strerror(xerrno));
1855           return;
1856         }
1857         break;
1858 
1859       default:
1860         pr_log_pri(PR_LOG_ERR, "error opening scoreboard: %s",
1861           strerror(errno));
1862         return;
1863     }
1864   }
1865   PRIVS_RELINQUISH
1866   pr_close_scoreboard(FALSE);
1867 
1868   pr_event_generate("core.startup", NULL);
1869 
1870   init_bindings();
1871 
1872   /* Check our shutdown status */
1873   if (check_shutmsg(permanent_pool, PR_SHUTMSG_PATH, &shut, &deny, &disc,
1874       shutmsg, sizeof(shutmsg)) == 1) {
1875     shutting_down = TRUE;
1876   }
1877 
1878   /* Finally, call right into fork_server() to start servicing the
1879    * connection immediately.
1880    */
1881   fork_server(STDIN_FILENO, main_server->listen, TRUE);
1882 }
1883 
standalone_main(void)1884 static void standalone_main(void) {
1885   int res = 0;
1886 
1887   if (nodaemon) {
1888     log_stderr(quiet ? FALSE : TRUE);
1889     close(fileno(stdin));
1890     close(fileno(stdout));
1891 
1892   } else {
1893     log_stderr(FALSE);
1894     daemonize();
1895   }
1896 
1897   PRIVS_ROOT
1898   pr_delete_scoreboard();
1899   res = pr_open_scoreboard(O_RDWR);
1900   if (res < 0) {
1901     PRIVS_RELINQUISH
1902 
1903     switch (res) {
1904       case PR_SCORE_ERR_BAD_MAGIC:
1905         pr_log_pri(PR_LOG_ERR,
1906           "error opening scoreboard: bad/corrupted file");
1907         return;
1908 
1909       case PR_SCORE_ERR_OLDER_VERSION:
1910         pr_log_pri(PR_LOG_ERR,
1911           "error opening scoreboard: bad version (too old)");
1912         return;
1913 
1914       case PR_SCORE_ERR_NEWER_VERSION:
1915         pr_log_pri(PR_LOG_ERR,
1916           "error opening scoreboard: bad version (too new)");
1917         return;
1918 
1919       default:
1920         pr_log_pri(PR_LOG_ERR, "error opening scoreboard: %s", strerror(errno));
1921         return;
1922     }
1923   }
1924   PRIVS_RELINQUISH
1925   pr_close_scoreboard(TRUE);
1926 
1927   pr_event_generate("core.startup", NULL);
1928 
1929   init_bindings();
1930 
1931   pr_log_pri(PR_LOG_NOTICE, "ProFTPD %s (built %s) standalone mode STARTUP",
1932     PROFTPD_VERSION_TEXT " " PR_STATUS, BUILD_STAMP);
1933 
1934   if (pr_pidfile_write() < 0) {
1935     fprintf(stderr, "error opening PidFile '%s': %s\n", pr_pidfile_get(),
1936       strerror(errno));
1937     exit(1);
1938   }
1939 
1940   daemon_loop();
1941 }
1942 
1943 extern char *optarg;
1944 extern int optind, opterr, optopt;
1945 
1946 #ifdef HAVE_GETOPT_LONG
1947 static struct option opts[] = {
1948   { "nocollision",    0, NULL, 'N' },
1949   { "nodaemon",	      0, NULL, 'n' },
1950   { "quiet",	      0, NULL, 'q' },
1951   { "debug",	      1, NULL, 'd' },
1952   { "define",	      1, NULL, 'D' },
1953   { "config",	      1, NULL, 'c' },
1954   { "persistent",     1, NULL, 'p' },
1955   { "list",           0, NULL, 'l' },
1956   { "version",        0, NULL, 'v' },
1957   { "settings",       0, NULL, 'V' },
1958   { "version-status", 0, NULL, 1   },
1959   { "configtest",     0, NULL, 't' },
1960   { "help",	      0, NULL, 'h' },
1961   { "ipv4",           0, NULL, '4' },
1962   { "ipv6",           0, NULL, '6' },
1963   { NULL,	      0, NULL,  0  }
1964 };
1965 #endif /* HAVE_GETOPT_LONG */
1966 
show_settings(void)1967 static void show_settings(void) {
1968 #ifdef HAVE_UNAME
1969   int res;
1970   struct utsname uts;
1971 #endif /* !HAVE_UNAME */
1972 
1973   printf("%s", "Compile-time Settings:\n");
1974   printf("%s", "  Version: " PROFTPD_VERSION_TEXT " " PR_STATUS "\n");
1975 
1976 #ifdef HAVE_UNAME
1977   /* We use uname(2) to get the 'machine', which will tell us whether
1978    * we're a 32- or 64-bit machine.
1979    */
1980   res = uname(&uts);
1981   if (res < 0) {
1982     printf("%s", "  Platform: " PR_PLATFORM " [unavailable]\n");
1983 
1984   } else {
1985     printf("  Platform: " PR_PLATFORM " [%s %s %s]\n", uts.sysname,
1986       uts.release, uts.machine);
1987   }
1988 #else
1989   printf("%s", "  Platform: " PR_PLATFORM " [unknown]\n");
1990 #endif /* !HAVE_UNAME */
1991 
1992   printf("%s", "  Built: " BUILD_STAMP "\n");
1993   printf("%s", "  Built With:\n    configure " PR_BUILD_OPTS "\n\n");
1994 
1995   printf("%s", "  CFLAGS: " PR_BUILD_CFLAGS "\n");
1996   printf("%s", "  LDFLAGS: " PR_BUILD_LDFLAGS "\n");
1997   printf("%s", "  LIBS: " PR_BUILD_LIBS "\n");
1998 
1999   /* Files/paths */
2000   printf("%s", "\n  Files:\n");
2001   printf("%s", "    Configuration File:\n");
2002   printf("%s", "      " PR_CONFIG_FILE_PATH "\n");
2003   printf("%s", "    Pid File:\n");
2004   printf("%s", "      " PR_PID_FILE_PATH "\n");
2005   printf("%s", "    Scoreboard File:\n");
2006   printf("%s", "      " PR_RUN_DIR "/proftpd.scoreboard\n");
2007 #ifdef PR_USE_DSO
2008   printf("%s", "    Header Directory:\n");
2009   printf("%s", "      " PR_INCLUDE_DIR "/proftpd\n");
2010   printf("%s", "    Shared Module Directory:\n");
2011   printf("%s", "      " PR_LIBEXEC_DIR "\n");
2012 #endif /* PR_USE_DSO */
2013 
2014   /* Informational */
2015   printf("%s", "\n  Info:\n");
2016 #if SIZEOF_UID_T == SIZEOF_INT
2017   printf("    + Max supported UID: %u\n", UINT_MAX);
2018 #elif SIZEOF_UID_T == SIZEOF_LONG
2019   printf("    + Max supported UID: %lu\n", ULONG_MAX);
2020 #elif SIZEOF_UID_T == SIZEOF_LONG_LONG
2021   printf("    + Max supported UID: %llu\n", ULLONG_MAX);
2022 #endif
2023 
2024 #if SIZEOF_GID_T == SIZEOF_INT
2025   printf("    + Max supported GID: %u\n", UINT_MAX);
2026 #elif SIZEOF_GID_T == SIZEOF_LONG
2027   printf("    + Max supported GID: %lu\n", ULONG_MAX);
2028 #elif SIZEOF_GID_T == SIZEOF_LONG_LONG
2029   printf("    + Max supported GID: %llu\n", ULLONG_MAX);
2030 #endif
2031 
2032   /* Feature settings */
2033   printf("%s", "\n  Features:\n");
2034 #ifdef PR_USE_AUTO_SHADOW
2035   printf("%s", "    + Autoshadow support\n");
2036 #else
2037   printf("%s", "    - Autoshadow support\n");
2038 #endif /* PR_USE_AUTO_SHADOW */
2039 
2040 #ifdef PR_USE_CTRLS
2041   printf("%s", "    + Controls support\n");
2042 #else
2043   printf("%s", "    - Controls support\n");
2044 #endif /* PR_USE_CTRLS */
2045 
2046 #if defined(PR_USE_CURSES) && defined(HAVE_LIBCURSES)
2047   printf("%s", "    + curses support\n");
2048 #else
2049   printf("%s", "    - curses support\n");
2050 #endif /* PR_USE_CURSES && HAVE_LIBCURSES */
2051 
2052 #ifdef PR_USE_DEVEL
2053   printf("%s", "    + Developer support\n");
2054 #else
2055   printf("%s", "    - Developer support\n");
2056 #endif /* PR_USE_DEVEL */
2057 
2058 #ifdef PR_USE_DSO
2059   printf("%s", "    + DSO support\n");
2060 #else
2061   printf("%s", "    - DSO support\n");
2062 #endif /* PR_USE_DSO */
2063 
2064 #ifdef PR_USE_IPV6
2065   printf("%s", "    + IPv6 support\n");
2066 #else
2067   printf("%s", "    - IPv6 support\n");
2068 #endif /* PR_USE_IPV6 */
2069 
2070 #ifdef PR_USE_LARGEFILES
2071   printf("%s", "    + Largefile support\n");
2072 #else
2073   printf("%s", "    - Largefile support\n");
2074 #endif /* PR_USE_LARGEFILES */
2075 
2076 #ifdef PR_USE_LASTLOG
2077   printf("%s", "    + Lastlog support\n");
2078 #else
2079   printf("%s", "    - Lastlog support\n");
2080 #endif /* PR_USE_LASTLOG */
2081 
2082 #ifdef PR_USE_MEMCACHE
2083   printf("%s", "    + Memcache support\n");
2084 #else
2085   printf("%s", "    - Memcache support\n");
2086 #endif /* PR_USE_MEMCACHE */
2087 
2088 #if defined(PR_USE_NCURSESW) && defined(HAVE_LIBNCURSESW)
2089   printf("%s", "    + ncursesw support\n");
2090 #elif defined(PR_USE_NCURSES) && defined(HAVE_LIBNCURSES)
2091   printf("%s", "    + ncurses support\n");
2092 #else
2093   printf("%s", "    - ncurses support\n");
2094 #endif
2095 
2096 #ifdef PR_USE_NLS
2097   printf("%s", "    + NLS support\n");
2098 #else
2099   printf("%s", "    - NLS support\n");
2100 #endif /* PR_USE_NLS */
2101 
2102 #ifdef PR_USE_OPENSSL
2103 # ifdef PR_USE_OPENSSL_FIPS
2104     printf("    + OpenSSL support (%s, FIPS enabled)\n", OPENSSL_VERSION_TEXT);
2105 # else
2106 #  ifdef LIBRESSL_VERSION_NUMBER
2107     printf("    + OpenSSL support (%s, LibreSSL)\n", OPENSSL_VERSION_TEXT);
2108 #  else
2109     printf("    + OpenSSL support (%s)\n", OPENSSL_VERSION_TEXT);
2110 #  endif /* Have LibreSSL */
2111 # endif /* PR_USE_OPENSSL_FIPS */
2112 #else
2113   printf("%s", "    - OpenSSL support\n");
2114 #endif /* PR_USE_OPENSSL */
2115 
2116 #ifdef PR_USE_PCRE
2117   printf("%s", "    + PCRE support\n");
2118 #else
2119   printf("%s", "    - PCRE support\n");
2120 #endif /* PR_USE_PCRE */
2121 
2122 #ifdef PR_USE_FACL
2123   printf("%s", "    + POSIX ACL support\n");
2124 #else
2125   printf("%s", "    - POSIX ACL support\n");
2126 #endif /* PR_USE_FACL */
2127 
2128 #ifdef PR_USE_REDIS
2129   printf("%s", "    + Redis support\n");
2130 #else
2131   printf("%s", "    - Redis support\n");
2132 #endif /* PR_USE_REDIS */
2133 
2134 #ifdef PR_USE_SENDFILE
2135   printf("%s", "    + Sendfile support\n");
2136 #else
2137   printf("%s", "    - Sendfile support\n");
2138 #endif /* PR_USE_SENDFILE */
2139 
2140 #ifdef PR_USE_SHADOW
2141   printf("%s", "    + Shadow file support\n");
2142 #else
2143   printf("%s", "    - Shadow file support\n");
2144 #endif /* PR_USE_SHADOW */
2145 
2146 #ifdef PR_USE_SODIUM
2147   printf("%s", "    + Sodium support\n");
2148 #else
2149   printf("%s", "    - Sodium support\n");
2150 #endif /* PR_USE_SODIUM */
2151 
2152 #ifdef PR_USE_TRACE
2153   printf("%s", "    + Trace support\n");
2154 #else
2155   printf("%s", "    - Trace support\n");
2156 #endif /* PR_USE_TRACE */
2157 
2158 #ifdef PR_USE_XATTR
2159   printf("%s", "    + xattr support\n");
2160 #else
2161   printf("%s", "    - xattr support\n");
2162 #endif /* PR_USE_XATTR */
2163 
2164   /* Tunable settings */
2165   printf("%s", "\n  Tunable Options:\n");
2166   printf("    PR_TUNABLE_BUFFER_SIZE = %u\n", PR_TUNABLE_BUFFER_SIZE);
2167   printf("    PR_TUNABLE_DEFAULT_RCVBUFSZ = %u\n", PR_TUNABLE_DEFAULT_RCVBUFSZ);
2168   printf("    PR_TUNABLE_DEFAULT_SNDBUFSZ = %u\n", PR_TUNABLE_DEFAULT_SNDBUFSZ);
2169   printf("    PR_TUNABLE_ENV_MAX = %u\n", PR_TUNABLE_ENV_MAX);
2170   printf("    PR_TUNABLE_GLOBBING_MAX_MATCHES = %lu\n", PR_TUNABLE_GLOBBING_MAX_MATCHES);
2171   printf("    PR_TUNABLE_GLOBBING_MAX_RECURSION = %u\n", PR_TUNABLE_GLOBBING_MAX_RECURSION);
2172   printf("    PR_TUNABLE_HASH_TABLE_SIZE = %u\n", PR_TUNABLE_HASH_TABLE_SIZE);
2173   printf("    PR_TUNABLE_LOGIN_MAX = %u\n", PR_TUNABLE_LOGIN_MAX);
2174   printf("    PR_TUNABLE_NEW_POOL_SIZE = %u\n", PR_TUNABLE_NEW_POOL_SIZE);
2175   printf("    PR_TUNABLE_PATH_MAX = %u\n", PR_TUNABLE_PATH_MAX);
2176   printf("    PR_TUNABLE_SCOREBOARD_BUFFER_SIZE = %u\n",
2177     PR_TUNABLE_SCOREBOARD_BUFFER_SIZE);
2178   printf("    PR_TUNABLE_SCOREBOARD_SCRUB_TIMER = %u\n",
2179     PR_TUNABLE_SCOREBOARD_SCRUB_TIMER);
2180   printf("    PR_TUNABLE_SELECT_TIMEOUT = %u\n", PR_TUNABLE_SELECT_TIMEOUT);
2181   printf("    PR_TUNABLE_TIMEOUTIDENT = %u\n", PR_TUNABLE_TIMEOUTIDENT);
2182   printf("    PR_TUNABLE_TIMEOUTIDLE = %u\n", PR_TUNABLE_TIMEOUTIDLE);
2183   printf("    PR_TUNABLE_TIMEOUTLINGER = %u\n", PR_TUNABLE_TIMEOUTLINGER);
2184   printf("    PR_TUNABLE_TIMEOUTLOGIN = %u\n", PR_TUNABLE_TIMEOUTLOGIN);
2185   printf("    PR_TUNABLE_TIMEOUTNOXFER = %u\n", PR_TUNABLE_TIMEOUTNOXFER);
2186   printf("    PR_TUNABLE_TIMEOUTSTALLED = %u\n", PR_TUNABLE_TIMEOUTSTALLED);
2187   printf("    PR_TUNABLE_XFER_SCOREBOARD_UPDATES = %u\n\n",
2188     PR_TUNABLE_XFER_SCOREBOARD_UPDATES);
2189 }
2190 
2191 static struct option_help {
2192   const char *long_opt, *short_opt, *desc;
2193 
2194 } opts_help[] = {
2195   { "--help", "-h",
2196     "Display proftpd usage"},
2197 
2198   { "--nocollision", "-N",
2199     "Disable address/port collision checking" },
2200 
2201   { "--nodaemon", "-n",
2202     "Disable background daemon mode (and send all output to stderr)" },
2203 
2204   { "--quiet", "-q",
2205     "Don't send output to stderr when running with -n or --nodaemon" },
2206 
2207   { "--debug", "-d [level]",
2208     "Set debugging level (0-10, 10 = most debugging)" },
2209 
2210   { "--define", "-D [definition]",
2211     "Set arbitrary IfDefine definition" },
2212 
2213   { "--config", "-c [config-file]",
2214     "Specify alternate configuration file" },
2215 
2216   { "--persistent", "-p [0|1]",
2217     "Enable/disable default persistent passwd support" },
2218 
2219   { "--list", "-l",
2220     "List all compiled-in modules" },
2221 
2222   { "--serveraddr", "-S",
2223     "Specify IP address for server config" },
2224 
2225   { "--configtest", "-t",
2226     "Test the syntax of the specified config" },
2227 
2228   { "--settings", "-V",
2229     "Print compile-time settings and exit" },
2230 
2231   { "--version", "-v",
2232     "Print version number and exit" },
2233 
2234   { "--version-status", "-vv",
2235     "Print extended version information and exit" },
2236 
2237   { "--nofork", "-X",
2238     "Non-forking debug mode; exits after one session" },
2239 
2240   { "--ipv4", "-4",
2241     "Support IPv4 connections only" },
2242 
2243   { "--ipv6", "-6",
2244     "Support IPv6 connections" },
2245 
2246   { NULL, NULL, NULL }
2247 };
2248 
show_usage(int exit_code)2249 static void show_usage(int exit_code) {
2250   struct option_help *h;
2251 
2252   printf("%s", "usage: proftpd [options]\n");
2253   for (h = opts_help; h->long_opt; h++) {
2254 #ifdef HAVE_GETOPT_LONG
2255     printf(" %s, %s\n ", h->short_opt, h->long_opt);
2256 #else /* HAVE_GETOPT_LONG */
2257     printf(" %s\n", h->short_opt);
2258 #endif /* HAVE_GETOPT_LONG */
2259     printf("    %s\n", h->desc);
2260   }
2261 
2262   exit(exit_code);
2263 }
2264 
main(int argc,char * argv[],char ** envp)2265 int main(int argc, char *argv[], char **envp) {
2266   int optc, show_version = 0;
2267   const char *cmdopts = "D:NVc:d:hlnp:qS:tvX46";
2268   mode_t *main_umask = NULL;
2269   socklen_t peerlen;
2270   struct sockaddr peer;
2271 
2272 #ifdef HAVE_SET_AUTH_PARAMETERS
2273   (void) set_auth_parameters(argc, argv);
2274 #endif
2275 
2276 #ifdef HAVE_TZSET
2277   /* Preserve timezone information in jailed environments.
2278    */
2279   tzset();
2280 #endif
2281 
2282   memset(&session, 0, sizeof(session));
2283 
2284   pr_fs_close_extra_fds();
2285   pr_proctitle_init(argc, argv, envp);
2286 
2287   /* Seed rand */
2288   pr_random_init();
2289 
2290   /* getpeername() fails if the fd isn't a socket */
2291   peerlen = sizeof(peer);
2292   memset(&peer, 0, peerlen);
2293   if (getpeername(fileno(stdin), &peer, &peerlen) != -1)
2294     log_stderr(FALSE);
2295 
2296   /* Open the syslog */
2297   log_opensyslog(NULL);
2298 
2299   /* Initialize the memory subsystem here */
2300   init_pools();
2301 
2302   /* Command line options supported:
2303    *
2304    * -D parameter       set run-time configuration parameter
2305    * --define parameter
2306    * -V
2307    * --settings         report compile-time settings
2308    * -c path            set the configuration path
2309    * --config path
2310    * -d n               set the debug level
2311    * --debug n
2312    * -q                 quiet mode; don't log to stderr when not daemonized
2313    * --quiet
2314    * -N                 disable address/port collision checks
2315    * --nocollision
2316    * -n                 standalone server does not daemonize, all logging
2317    * --nodaemon         redirected to stderr
2318    * -S                 specify the IP address for the 'server config',
2319    * --serveraddr       rather than using DNS on the hostname
2320    * -t                 syntax check of the configuration file
2321    * --configtest
2322    * -v                 report version number
2323    * --version
2324    * -X
2325    * --nofork           debug/non-fork mode
2326    * -4                 support IPv4 connections only
2327    * --ipv4
2328    * -6                 support IPv6 connections
2329    * --ipv6
2330    */
2331 
2332   opterr = 0;
2333   while ((optc =
2334 #ifdef HAVE_GETOPT_LONG
2335 	 getopt_long(argc, argv, cmdopts, opts, NULL)
2336 #else /* HAVE_GETOPT_LONG */
2337 	 getopt(argc, argv, cmdopts)
2338 #endif /* HAVE_GETOPT_LONG */
2339 	 ) != -1) {
2340     switch (optc) {
2341 
2342     case 'D':
2343       if (!optarg) {
2344         pr_log_pri(PR_LOG_WARNING, "fatal: -D requires definition parameter");
2345         exit(1);
2346       }
2347 
2348       pr_define_add(optarg, TRUE);
2349       break;
2350 
2351     case 'V':
2352       show_settings();
2353       exit(0);
2354       break;
2355 
2356     case 'N':
2357       AddressCollisionCheck = FALSE;
2358       break;
2359 
2360     case 'n':
2361       nodaemon++;
2362 #ifdef PR_USE_DEVEL
2363       pr_pool_debug_set_flags(PR_POOL_DEBUG_FL_OOM_DUMP_POOLS);
2364 #endif
2365       break;
2366 
2367     case 'q':
2368       quiet++;
2369       break;
2370 
2371     case 'd':
2372       if (!optarg) {
2373         pr_log_pri(PR_LOG_WARNING, "fatal: -d requires debug level parameter");
2374         exit(1);
2375       }
2376       pr_log_setdebuglevel(atoi(optarg));
2377 
2378       /* If the admin uses -d on the command-line, they explicitly WANT
2379        * debug logging, thus make sure the default SyslogLevel is set to
2380        * DEBUG (rather than NOTICE); see Bug#3983.
2381        */
2382       pr_log_setdefaultlevel(PR_LOG_DEBUG);
2383       break;
2384 
2385     case 'c':
2386       if (!optarg) {
2387         pr_log_pri(PR_LOG_WARNING,
2388           "fatal: -c requires configuration path parameter");
2389         exit(1);
2390       }
2391 
2392       /* Note: we delay sanity-checking the given path until after the FSIO
2393        * layer has been initialized.
2394        */
2395       config_filename = strdup(optarg);
2396       break;
2397 
2398     case 'l':
2399       modules_list2(NULL, PR_MODULES_LIST_FL_SHOW_STATIC);
2400       exit(0);
2401       break;
2402 
2403     case 'S':
2404       if (!optarg) {
2405         pr_log_pri(PR_LOG_WARNING, "fatal: -S requires IP address parameter");
2406         exit(1);
2407       }
2408 
2409       if (pr_netaddr_set_localaddr_str(optarg) < 0) {
2410         pr_log_pri(PR_LOG_WARNING,
2411           "fatal: unable to use '%s' as server address: %s", optarg,
2412           strerror(errno));
2413         exit(1);
2414       }
2415       break;
2416 
2417     case 't':
2418       syntax_check = 1;
2419       printf("%s", "Checking syntax of configuration file\n");
2420       fflush(stdout);
2421       break;
2422 
2423     /* Note: This is now unused, and should be deprecated in the next release.
2424      * See Bug#3952 for details.
2425      */
2426     case 'p': {
2427       if (!optarg ||
2428           (atoi(optarg) != 1 && atoi(optarg) != 0)) {
2429         pr_log_pri(PR_LOG_WARNING,
2430           "fatal: -p requires Boolean (0|1) parameter");
2431         exit(1);
2432       }
2433 
2434       break;
2435     }
2436 
2437     case 'v':
2438       show_version++;
2439       break;
2440 
2441     case 'X':
2442       no_forking = TRUE;
2443       break;
2444 
2445     case 1:
2446       show_version = 2;
2447       break;
2448 
2449     case 'h':
2450       show_usage(0);
2451       break;
2452 
2453     case '4':
2454       pr_netaddr_disable_ipv6();
2455       break;
2456 
2457     case '6':
2458       pr_netaddr_enable_ipv6();
2459       break;
2460 
2461     case '?':
2462       pr_log_pri(PR_LOG_WARNING, "unknown option: %c", (char) optopt);
2463       show_usage(1);
2464       break;
2465     }
2466   }
2467 
2468   /* If we have any leftover parameters, it's an error. */
2469   if (argv[optind]) {
2470     pr_log_pri(PR_LOG_WARNING, "fatal: unknown parameter: '%s'", argv[optind]);
2471     exit(1);
2472   }
2473 
2474   if (show_version &&
2475       show_version == 1) {
2476     printf("%s", "ProFTPD Version " PROFTPD_VERSION_TEXT "\n");
2477     exit(0);
2478   }
2479 
2480   mpid = getpid();
2481 
2482   /* Initialize sub-systems */
2483   init_signals();
2484   init_pools();
2485   init_privs();
2486   init_log();
2487   init_regexp();
2488   init_inet();
2489   init_netio();
2490   init_netaddr();
2491   init_fs();
2492   init_class();
2493   free_bindings();
2494   init_config();
2495   init_dirtree();
2496   init_stash();
2497   init_json();
2498 
2499 #ifdef PR_USE_CTRLS
2500   init_ctrls();
2501 #endif /* PR_USE_CTRLS */
2502 
2503   var_init();
2504   modules_init();
2505 
2506 #ifdef PR_USE_NLS
2507 # ifdef HAVE_LOCALE_H
2508   /* Initialize the locale based on environment variables. */
2509   if (setlocale(LC_ALL, "") == NULL) {
2510     const char *env_lang;
2511 
2512     env_lang = pr_env_get(permanent_pool, "LANG");
2513     pr_log_pri(PR_LOG_WARNING, "warning: unknown/unsupported LANG environment "
2514       "variable '%s', ignoring", env_lang);
2515 
2516     setlocale(LC_ALL, "C");
2517 
2518   } else {
2519     /* Make sure that LC_NUMERIC is always set to "C", so as not to interfere
2520      * with formatting of strings (like printing out floats in SQL query
2521      * strings).
2522      */
2523     setlocale(LC_NUMERIC, "C");
2524   }
2525 # endif /* !HAVE_LOCALE_H */
2526 
2527   encode_init();
2528 #endif /* PR_USE_NLS */
2529 
2530   /* Now, once the modules have had a chance to initialize themselves
2531    * but before the configuration stream is actually parsed, check
2532    * that the given configuration path is valid.
2533    */
2534   if (pr_fs_valid_path(config_filename) < 0) {
2535     pr_log_pri(PR_LOG_WARNING, "fatal: -c requires an absolute path");
2536     exit(1);
2537   }
2538 
2539   pr_parser_prepare(NULL, NULL);
2540 
2541   pr_event_generate("core.preparse", NULL);
2542 
2543   if (pr_parser_parse_file(NULL, config_filename, NULL, 0) < 0) {
2544     /* Note: EPERM is used to indicate the presence of unrecognized
2545      * configuration directives in the parsed file(s).
2546      */
2547     if (errno != EPERM) {
2548       pr_log_pri(PR_LOG_WARNING,
2549         "fatal: unable to read configuration file '%s': %s", config_filename,
2550         strerror(errno));
2551     }
2552 
2553     exit(1);
2554   }
2555 
2556   if (pr_parser_cleanup() < 0) {
2557     pr_log_pri(PR_LOG_WARNING,
2558       "fatal: error processing configuration file '%s': "
2559       "unclosed configuration section", config_filename);
2560     exit(1);
2561   }
2562 
2563   if (fixup_servers(server_list) < 0) {
2564     pr_log_pri(PR_LOG_WARNING,
2565       "fatal: error processing configuration file '%s'", config_filename);
2566     exit(1);
2567   }
2568 
2569   pr_event_generate("core.postparse", NULL);
2570 
2571   if (show_version == 2) {
2572     printf("ProFTPD Version: %s", PROFTPD_VERSION_TEXT " " PR_STATUS "\n");
2573     printf("  Scoreboard Version: %08x\n", PR_SCOREBOARD_VERSION);
2574     printf("  Built: %s\n\n", BUILD_STAMP);
2575 
2576     modules_list2(NULL, PR_MODULES_LIST_FL_SHOW_VERSION);
2577     exit(0);
2578   }
2579 
2580   /* We're only doing a syntax check of the configuration file. */
2581   if (syntax_check) {
2582     printf("%s", "Syntax check complete.\n");
2583     pr_session_end(PR_SESS_END_FL_SYNTAX_CHECK);
2584   }
2585 
2586   /* Security */
2587   {
2588     uid_t *uid = (uid_t *) get_param_ptr(main_server->conf, "UserID", FALSE);
2589     gid_t *gid = (gid_t *) get_param_ptr(main_server->conf, "GroupID", FALSE);
2590 
2591     daemon_uid = (uid != NULL ? *uid : PR_ROOT_UID);
2592     daemon_gid = (gid != NULL ? *gid : PR_ROOT_GID);
2593   }
2594 
2595   if (daemon_uid != PR_ROOT_UID) {
2596     pr_log_debug(DEBUG9, "ignoring supplemental groups for non-root UID %lu",
2597       (unsigned long) daemon_uid);
2598   }
2599 
2600   /* After configuration is complete, make sure that passwd, group
2601    * aren't held open (unnecessary fds for master daemon)
2602    */
2603   endpwent();
2604   endgrent();
2605 
2606   main_umask = get_param_ptr(main_server->conf, "Umask", FALSE);
2607   if (main_umask == NULL) {
2608     umask((mode_t) 0022);
2609 
2610   } else {
2611     umask(*main_umask);
2612   }
2613 
2614   /* Give up root and save our uid/gid for later use (if supported)
2615    * If we aren't currently root, PRIVS_SETUP will get rid of setuid
2616    * granted root and prevent further uid switching from being attempted.
2617    */
2618 
2619   PRIVS_SETUP(daemon_uid, daemon_gid)
2620 
2621 #ifndef PR_DEVEL_COREDUMP
2622   /* Test to make sure that our uid/gid is correct.  Try to do this in
2623    * a portable fashion *gah!*
2624    */
2625 
2626   if (geteuid() != daemon_uid) {
2627     pr_log_pri(PR_LOG_ERR, "unable to set UID to %s, current UID: %s",
2628       pr_uid2str(permanent_pool, daemon_uid),
2629       pr_uid2str(permanent_pool, geteuid()));
2630     exit(1);
2631   }
2632 
2633   if (getegid() != daemon_gid) {
2634     pr_log_pri(PR_LOG_ERR, "unable to set GID to %s, current GID: %s",
2635       pr_gid2str(permanent_pool, daemon_gid),
2636       pr_gid2str(permanent_pool, getegid()));
2637     exit(1);
2638   }
2639 #endif /* PR_DEVEL_COREDUMP */
2640 
2641   switch (ServerType) {
2642     case SERVER_STANDALONE:
2643       standalone_main();
2644       break;
2645 
2646     case SERVER_INETD:
2647       /* Reset the variable containing the pid of the master/daemon process;
2648        * it should only be non-zero in the case of standalone daemons.
2649        */
2650       mpid = 0;
2651       inetd_main();
2652       break;
2653   }
2654 
2655 #ifdef PR_DEVEL_NO_DAEMON
2656   PRIVS_ROOT
2657   chdir(PR_RUN_DIR);
2658 #endif /* PR_DEVEL_NO_DAEMON */
2659 
2660   return 0;
2661 }
2662