static void capa_user (const char *name, struct pop3d_session *session) { if (state == INITIAL) pop3d_outf ("XTLSREQUIRED\n"); else pop3d_outf ("USER\n"); }
int pop3d_capa (char *arg, struct pop3d_session *sess) { if (strlen (arg) != 0) return ERR_BAD_ARGS; pop3d_outf ("+OK Capability list follows\n"); mu_list_foreach (sess->capa, print_capa, sess); pop3d_outf (".\n"); return OK; }
static void capa_stls (const char *name, struct pop3d_session *session) { if ((session->tls == tls_ondemand || session->tls == tls_required) && tls_available && tls_done == 0) pop3d_outf ("%s\n", name); }
int pop3d_uidl (char *arg, struct pop3d_session *sess) { size_t mesgno; char uidl[128]; mu_message_t msg; mu_attribute_t attr; if (state != TRANSACTION) return ERR_WRONG_STATE; if (strchr (arg, ' ') != NULL) return ERR_BAD_ARGS; if (strlen (arg) == 0) { size_t total = 0; pop3d_outf ("+OK\n"); mu_mailbox_messages_count (mbox, &total); for (mesgno = 1; mesgno <= total; mesgno++) { mu_mailbox_get_message (mbox, mesgno, &msg); mu_message_get_attribute (msg, &attr); if (!pop3d_is_deleted (attr)) { mu_message_get_uidl (msg, uidl, sizeof (uidl), NULL); pop3d_outf ("%s %s\n", mu_umaxtostr (0, mesgno), uidl); } } pop3d_outf (".\n"); } else { mesgno = strtoul (arg, NULL, 10); if (mu_mailbox_get_message (mbox, mesgno, &msg) != 0) return ERR_NO_MESG; mu_message_get_attribute (msg, &attr); if (pop3d_is_deleted (attr)) return ERR_MESG_DELE; mu_message_get_uidl (msg, uidl, sizeof (uidl), NULL); pop3d_outf ("+OK %s %s\n", mu_umaxtostr (0, mesgno), uidl); } return OK; }
static int print_capa (void *item, void *data) { struct pop3d_capa *cp = item; struct pop3d_session *session = data; if (cp->type == capa_func) { cp->value.func (cp->name, session); } else { pop3d_outf ("%s", cp->name); if (cp->value.string) pop3d_outf ("%s", cp->value.string); pop3d_outf ("\n"); } return 0; }
void login_delay_capa () { DBM_FILE db; if (login_delay && open_stat_db (&db, MU_STREAM_RDWR) == 0) { pop3d_outf ("LOGIN-DELAY %s\r\n", mu_umaxtostr (0, login_delay)); mu_dbm_close (db); } }
int pop3d_stat (char *arg) { size_t mesgno; size_t size = 0; size_t lines = 0; size_t total = 0; size_t num = 0; size_t tsize = 0; mu_message_t msg = NULL; mu_attribute_t attr = NULL; if (strlen (arg) != 0) return ERR_BAD_ARGS; if (state != TRANSACTION) return ERR_WRONG_STATE; /* rfc1939: if the POP3 server host internally represents end-of-line as a single character, then the POP3 server simply counts each occurrence of this character in a message as two octets. */ mu_mailbox_messages_count (mbox, &total); for (mesgno = 1; mesgno <= total; mesgno++) { mu_mailbox_get_message (mbox, mesgno, &msg); mu_message_get_attribute (msg, &attr); /* rfc1939: Note that messages marked as deleted are not counted in either total. */ if (!pop3d_is_deleted (attr)) { mu_message_size (msg, &size); mu_message_lines (msg, &lines); tsize += size + lines; num++; } } pop3d_outf ("+OK %s %s\r\n", mu_umaxtostr (0, num), mu_umaxtostr (1, tsize)); return OK; }
static void capa_implementation (const char *name, struct pop3d_session *session) { if (state == TRANSACTION) /* let's not advertise to just anyone */ pop3d_outf ("%s %s\n", name, PACKAGE_STRING); }
/* 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; }