void imap4d_child_signal_setup (RETSIGTYPE (*handler) (int signo)) { static int sigtab[] = { SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSTOP, SIGPIPE, SIGABRT, SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGALRM }; mu_set_signals (handler, sigtab, MU_ARRAY_SIZE (sigtab)); }
int main (int argc, char **argv) { struct group *gr; int status = 0; static int sigtab[] = { SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSTOP, SIGPIPE, SIGABRT }; imap4d_argc = argc; imap4d_argv = argv; /* Native Language Support */ MU_APP_INIT_NLS (); state = STATE_NONAUTH; /* Starting state in non-auth. */ MU_AUTH_REGISTER_ALL_MODULES (); /* Register the desired formats. */ mu_register_local_mbox_formats (); imap4d_capability_init (); #ifdef WITH_TLS mu_gocs_register ("tls", mu_tls_module_init); #endif /* WITH_TLS */ #ifdef WITH_GSASL mu_gocs_register ("gsasl", mu_gsasl_module_init); #endif mu_tcpwrapper_cfg_init (); mu_acl_cfg_init (); mu_m_server_cfg_init (); mu_argp_init (program_version, NULL); mu_m_server_create (&server, program_version); mu_m_server_set_conn (server, imap4d_connection); mu_m_server_set_prefork (server, mu_tcp_wrapper_prefork); mu_m_server_set_mode (server, MODE_INTERACTIVE); mu_m_server_set_max_children (server, 20); /* FIXME mu_m_server_set_pidfile (); */ mu_m_server_set_default_port (server, 143); mu_m_server_set_timeout (server, 1800); /* RFC2060: 30 minutes. */ mu_m_server_set_strexit (server, mu_strexit); if (mu_app_init (&argp, imap4d_capa, imap4d_cfg_param, argc, argv, 0, NULL, server)) exit (EX_CONFIG); /* FIXME: No way to discern from EX_USAGE? */ if (login_disabled) imap4d_capability_add (IMAP_CAPA_LOGINDISABLED); #ifdef WITH_TLS if (tls_required) imap4d_capability_add (IMAP_CAPA_XTLSREQUIRED); #endif namespace_init (); auth_gssapi_init (); auth_gsasl_init (); #ifdef USE_LIBPAM if (!mu_pam_service) mu_pam_service = "gnu-imap4d"; #endif if (mu_m_server_mode (server) == MODE_DAEMON) { /* Normal operation: */ /* First we want our group to be mail so we can access the spool. */ errno = 0; gr = getgrnam ("mail"); if (gr == NULL) { if (errno == 0 || errno == ENOENT) { mu_error (_("%s: no such group"), "mail"); exit (EX_CONFIG); } else { mu_diag_funcall (MU_DIAG_ERROR, "getgrnam", "mail", errno); exit (EX_OSERR); } } if (setgid (gr->gr_gid) == -1) { mu_error (_("error setting mail group: %s"), mu_strerror (errno)); exit (EX_OSERR); } } /* Set the signal handlers. */ mu_set_signals (imap4d_master_signal, sigtab, MU_ARRAY_SIZE (sigtab)); /* Set up for syslog. */ openlog (MU_LOG_TAG (), LOG_PID, mu_log_facility); /* Redirect any stdout error from the library to syslog, they should not go to the client. */ { mu_debug_t debug; mu_diag_get_debug (&debug); mu_debug_set_print (debug, mu_diag_syslog_printer, NULL); mu_debug_default_printer = mu_debug_syslog_printer; } umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */ /* Check TLS environment, i.e. cert and key files */ #ifdef WITH_TLS starttls_init (); #endif /* WITH_TLS */ /* Actually run the daemon. */ if (mu_m_server_mode (server) == MODE_DAEMON) { mu_m_server_begin (server); status = mu_m_server_run (server); mu_m_server_end (server); mu_m_server_destroy (&server); } else { /* Make sure we are in the root directory. */ chdir ("/"); status = imap4d_mainloop (fileno (stdin), stdin, stdout); } if (status) mu_error (_("main loop status: %s"), mu_strerror (status)); /* Close the syslog connection and exit. */ closelog (); return status ? EX_SOFTWARE : EX_OK; }
int main (int argc, char **argv) { struct group *gr; int status = OK; static int sigtab[] = { SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSTOP, SIGPIPE }; /* Native Language Support */ MU_APP_INIT_NLS (); MU_AUTH_REGISTER_ALL_MODULES(); /* Register the desired formats. */ mu_register_local_mbox_formats (); #ifdef WITH_TLS mu_gocs_register ("tls", mu_tls_module_init); #endif /* WITH_TLS */ mu_tcpwrapper_cfg_init (); manlock_cfg_init (); mu_acl_cfg_init (); mu_m_server_cfg_init (pop3d_srv_param); mu_argp_init (NULL, NULL); mu_m_server_create (&server, program_version); mu_m_server_set_config_size (server, sizeof (struct pop3d_srv_config)); mu_m_server_set_conn (server, pop3d_connection); mu_m_server_set_prefork (server, mu_tcp_wrapper_prefork); mu_m_server_set_mode (server, MODE_INTERACTIVE); mu_m_server_set_max_children (server, 20); /* FIXME mu_m_server_set_pidfile (); */ mu_m_server_set_default_port (server, 110); mu_m_server_set_timeout (server, 600); mu_m_server_set_strexit (server, mu_strexit); mu_alloc_die_hook = pop3d_alloc_die; mu_log_syslog = 1; manlock_mandatory_locking = 1; #ifdef ENABLE_DBM set_dbm_safety (); #endif if (mu_app_init (&argp, pop3d_argp_capa, pop3d_cfg_param, argc, argv, 0, NULL, server)) exit (EX_CONFIG); /* FIXME: No way to discern from EX_USAGE? */ if (expire == 0) expire_on_exit = 1; #ifdef USE_LIBPAM if (!mu_pam_service) mu_pam_service = "gnu-pop3d"; #endif if (mu_m_server_mode (server) == MODE_INTERACTIVE && isatty (0)) { /* If input is a tty, switch to debug mode */ debug_mode = 1; } else { errno = 0; gr = getgrnam ("mail"); if (gr == NULL) { if (errno == 0 || errno == ENOENT) { mu_error (_("%s: no such group"), "mail"); exit (EX_CONFIG); } else { mu_diag_funcall (MU_DIAG_ERROR, "getgrnam", "mail", errno); exit (EX_OSERR); } } if (setgid (gr->gr_gid) == -1) { mu_error (_("error setting mail group: %s"), mu_strerror (errno)); exit (EX_OSERR); } } /* Set the signal handlers. */ mu_set_signals (pop3d_master_signal, sigtab, MU_ARRAY_SIZE (sigtab)); mu_stdstream_strerr_setup (mu_log_syslog ? MU_STRERR_SYSLOG : MU_STRERR_STDERR); umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */ /* Check TLS environment, i.e. cert and key files */ #ifdef WITH_TLS tls_available = mu_check_tls_environment (); if (tls_available) enable_stls (); #endif /* WITH_TLS */ /* Actually run the daemon. */ if (mu_m_server_mode (server) == MODE_DAEMON) { mu_m_server_begin (server); status = mu_m_server_run (server); mu_m_server_end (server); mu_m_server_destroy (&server); } else { /* Make sure we are in the root directory. */ chdir ("/"); status = pop3d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, tls_mode); } if (status) mu_error (_("main loop status: %s"), mu_strerror (status)); /* Close the syslog connection and exit. */ closelog (); return status ? EX_SOFTWARE : EX_OK; }
static enum mu_filter_result _xml_decoder (void *xd, enum mu_filter_command cmd, struct mu_filter_io *iobuf) { struct xml_decode_state *cp = xd; const char *iptr; size_t isize; char *optr; size_t osize; switch (cmd) { case mu_filter_init: DECODE_INIT (cp); return mu_filter_ok; case mu_filter_done: return mu_filter_ok; default: break; } iptr = iobuf->input; isize = iobuf->isize; optr = iobuf->output; osize = iobuf->osize; while (isize && osize) { switch (cp->phase) { case enc_init: nextchar (cp, *iptr); if (cp->phase == enc_init) { *optr++ = *iptr; --osize; } ++iptr; --isize; break; case enc_map: nextchar (cp, *iptr); if (cp->phase == enc_map || cp->phase == enc_finish || cp->phase == enc_char_ref) { ++iptr; --isize; } else if (cp->phase == enc_init) { *optr++ = *iptr++; --osize; --isize; } break; case enc_finish: *optr++ = cp->map->ch; --osize; DECODE_INIT (cp); break; case enc_rollback: *optr++ = cp->map->ent[cp->pos]; --osize; if (++cp->pos == cp->idx) DECODE_INIT (cp); break; case enc_char_ref: if (*iptr == 'x') { cp->base = 16; cp->buf[cp->idx++] = *iptr; ++iptr; --isize; } else cp->base = 10; cp->phase = enc_char_cont; break; case enc_char_cont: if (*iptr == ';') { *optr++ = cp->wc; --osize; ++iptr; --isize; DECODE_INIT (cp); } else if (cp->idx < MU_ARRAY_SIZE (cp->buf) && mu_isxdigit (*iptr)) { static char xdig[] = "0123456789ABCDEF"; int n = strchr (xdig, mu_toupper (*iptr)) - xdig; cp->wc = cp->wc * cp->base + n; cp->buf[cp->idx++] = *iptr; ++iptr; --isize; } else { cp->phase = enc_char_rollback; cp->pos = 0; } break; case enc_char_rollback: *optr++ = cp->buf[cp->pos++]; --osize; if (cp->pos == cp->idx) DECODE_INIT (cp); } } iobuf->isize -= isize; iobuf->osize -= osize; return mu_filter_ok; }
/* The main part of the daemon. This function reads input from the client and executes the proper functions. Also handles the bulk of error reporting. Arguments: ifd -- input descriptor ofd -- output descriptor tls -- initiate encrypted connection */ int pop3d_mainloop (int ifd, int ofd, enum tls_mode tls) { int status = OK; char buffer[512]; static int sigtab[] = { SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSTOP, SIGPIPE, SIGABRT, SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGALRM }; struct pop3d_session session; mu_set_signals (pop3d_child_signal, sigtab, MU_ARRAY_SIZE (sigtab)); if (tls == tls_unspecified) tls = tls_available ? tls_ondemand : tls_no; else if (tls != tls_no && !tls_available) { mu_error (_("TLS is not configured, but requested in the " "configuration")); tls = tls_no; } pop3d_setio (ifd, ofd, tls == tls_connection); if (tls == tls_required) initial_state = INITIAL; state = tls == tls_connection ? AUTHORIZATION : initial_state; pop3d_session_init (&session); session.tls = tls; /* FIXME: state should also be in the session? */ /* Prepare the shared secret for APOP. */ { char *local_hostname; status = mu_get_host_name (&local_hostname); if (status) { mu_diag_funcall (MU_DIAG_ERROR, "mu_get_host_name", NULL, status); exit (EXIT_FAILURE); } md5shared = mu_alloc (strlen (local_hostname) + 51); snprintf (md5shared, strlen (local_hostname) + 50, "<%u.%u@%s>", getpid (), (unsigned)time (NULL), local_hostname); free (local_hostname); } /* Lets boogie. */ pop3d_outf ("+OK POP3 Ready %s\n", md5shared); while (state != UPDATE && state != ABORT) { char *buf; char *arg, *cmd; pop3d_command_handler_t handler; pop3d_flush_output (); status = OK; buf = pop3d_readline (buffer, sizeof (buffer)); pop3d_parse_command (buf, &cmd, &arg); if (state == TRANSACTION && !mu_mailbox_is_updated (mbox)) { static mu_off_t mailbox_size; mu_off_t newsize = 0; mu_mailbox_get_size (mbox, &newsize); /* Did we shrink? First time save the size. */ if (!mailbox_size) mailbox_size = newsize; else if (newsize < mailbox_size) /* FIXME: Should it be a != ? */ pop3d_abquit (ERR_MBOX_SYNC); /* Out of sync, Bail out. */ } /* Refresh the Lock. */ manlock_touchlock (mbox); if ((handler = pop3d_find_command (cmd)) != NULL) status = handler (arg, &session); else status = ERR_BAD_CMD; if (status != OK) pop3d_outf ("-ERR %s\n", pop3d_error_string (status)); } pop3d_session_free (&session); pop3d_bye (); return status; }