#include #include #include #include "buffer.h" #include "constmap.h" #include "direntry.h" #include "exit.h" #include "fmt.h" #include "str.h" #include "stralloc.h" #include "auto_break.h" #include "auto_patrn.h" #include "auto_qmail.h" #include "auto_spawn.h" #include "auto_split.h" #include "auto_uids.h" #include "control.h" #include "spf.h" stralloc me = {0}; int meok; stralloc line = {0}; char num[FMT_ULONG]; void safeput(char *buf, unsigned int len) { char ch; while (len > 0) { ch = *buf; if ((ch < 32) || (ch > 126)) ch = '?'; buffer_put(buffer_1, &ch, 1); ++buf; --len; } } void do_int(char *fn, char *def, char *pre, char *post) { long i; buffer_puts(buffer_1, "\n"); buffer_puts(buffer_1, fn); buffer_puts(buffer_1, ": "); switch (control_readint(&i, fn)) { case 0: buffer_puts(buffer_1, "(Default.) "); buffer_puts(buffer_1, pre); buffer_puts(buffer_1, def); buffer_puts(buffer_1, post); buffer_puts(buffer_1, ".\n"); break; case 1: if (i < 0) i = 0; buffer_puts(buffer_1, pre); buffer_put(buffer_1, num, fmt_uint(num, i)); buffer_puts(buffer_1, post); buffer_puts(buffer_1, ".\n"); break; default: buffer_puts(buffer_1, "Oops! Trouble reading this file.\n"); break; } } void do_str(char *fn, int flagme, char *def, char *pre) { buffer_puts(buffer_1, "\n"); buffer_puts(buffer_1, fn); buffer_puts(buffer_1, ": "); switch (control_readline(&line, fn)) { case 0: buffer_puts(buffer_1, "(Default.) "); if (!stralloc_copys(&line, def)) { buffer_puts(buffer_1, "Oops! Out of memory.\n"); break; } if (flagme && meok) { if (!stralloc_copy(&line, &me)) { buffer_puts(buffer_1, "Oops! Out of memory.\n"); break; } } case 1: buffer_puts(buffer_1, pre); safeput(line.s, line.len); buffer_puts(buffer_1, ".\n"); break; default: buffer_puts(buffer_1, "Oops! Trouble reading this file.\n"); break; } } int do_lst(char *fn, char *def, char *pre, char *post) { int i; int j; buffer_puts(buffer_1, "\n"); buffer_puts(buffer_1, fn); buffer_puts(buffer_1, ": "); switch (control_readfile(&line, fn, 0)) { case 0: buffer_puts(buffer_1, "(Default.) "); buffer_puts(buffer_1, def); buffer_puts(buffer_1, "\n"); return 0; case 1: buffer_puts(buffer_1, "\n"); i = 0; for (j = 0; j < line.len; ++j) { if (!line.s[j]) { buffer_puts(buffer_1, pre); safeput(line.s + i, j - i); buffer_puts(buffer_1, post); buffer_puts(buffer_1, "\n"); i = j + 1; } } return 1; default: buffer_puts(buffer_1, "Oops! Trouble reading this file.\n"); return -1; } } int main() { DIR *dir; direntry *d; struct stat stmrh; struct stat stmrhcdb; buffer_puts(buffer_1, "s/qmail home directory: "); buffer_puts(buffer_1, auto_qmail); buffer_puts(buffer_1, ".\n"); buffer_puts(buffer_1, "user-ext delimiter: "); buffer_puts(buffer_1, auto_break); buffer_puts(buffer_1, ".\n"); buffer_puts(buffer_1, "paternalism (in decimal): "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_patrn)); buffer_puts(buffer_1, ".\n"); buffer_puts(buffer_1, "silent concurrency limit: "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_spawn)); buffer_puts(buffer_1, ".\n"); buffer_puts(buffer_1, "subdirectory split: "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_split)); buffer_puts(buffer_1, ".\n"); buffer_puts(buffer_1, "user ids: "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_uida)); buffer_puts(buffer_1, ", "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_uidd)); buffer_puts(buffer_1, ", "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_uidl)); buffer_puts(buffer_1, ", "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_uido)); buffer_puts(buffer_1, ", "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_uidp)); buffer_puts(buffer_1, ", "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_uidq)); buffer_puts(buffer_1, ", "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_uidr)); buffer_puts(buffer_1, ", "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_uids)); buffer_puts(buffer_1, ".\n"); buffer_puts(buffer_1, "group ids: "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_gidn)); buffer_puts(buffer_1, ", "); buffer_put(buffer_1, num, fmt_ulong(num, (unsigned long)auto_gidq)); buffer_puts(buffer_1, ".\n"); if (chdir(auto_qmail) == -1) { buffer_puts(buffer_1, "Oops! Unable to chdir to "); buffer_puts(buffer_1, auto_qmail); buffer_puts(buffer_1, ".\n"); buffer_flush(buffer_1); _exit(110); } if (chdir("control") == -1) { buffer_puts(buffer_1, "Oops! Unable to chdir to control.\n"); buffer_flush(buffer_1); _exit(110); } dir = opendir("."); if (!dir) { buffer_puts(buffer_1, "Oops! Unable to open current directory.\n"); buffer_flush(buffer_1); _exit(110); } meok = control_readline(&me, "me"); if (meok == -1) { buffer_puts(buffer_1, "Oops! Trouble reading control/me."); buffer_flush(buffer_1); _exit(112); } do_lst("authsenders", "No authenticated SMTP senders.", "Authenticated SMTP senders: ", ""); do_lst( "badhelo", "Any HELO/EHLO greeting is allowed.", "", " not accepted in HELO/EHLO; exception token is '!'."); do_lst( "badmailfrom", "Any MAIL FROM is allowed.", "", " are rejected or treated special in MAIL FROM depending on tokens: '!', '?', '=', '~', '+'."); do_lst("badloadertypes", "Any loader types are accepted.", "", " not accepted as loader type."); /* XXX: check badloadertypes.cdb contents */ buffer_puts(buffer_1, "\nbadloadertypes.cdb: "); if (stat("badloadertypes", &stmrh) == -1) if (stat("badloadertypes.cdb", &stmrhcdb) == -1) buffer_puts(buffer_1, "(Default.) No effect.\n"); else buffer_puts(buffer_1, "Oops! badloadertypes.cdb exists but badloadertypes doesn't.\n"); else if (stat("badloadertypes.cdb", &stmrhcdb) == -1) buffer_puts(buffer_1, "Oops! badloadertypes exists but badloadertypes.cdb doesn't.\n"); else if (stmrh.st_mtime > stmrhcdb.st_mtime) buffer_puts(buffer_1, "Oops! badloadertypes.cdb is older than badloadertypes.\n"); else buffer_puts(buffer_1, "Modified recently enough; hopefully up to date.\n"); do_lst("badmimetypes", "Any MIME types are accepted.", "", " not accepted as MIME type."); /* XXX: check badmimetypes.cdb contents */ buffer_puts(buffer_1, "\nbadmimetypes.cdb: "); if (stat("badmimetypes", &stmrh) == -1) if (stat("badmimetypes.cdb", &stmrhcdb) == -1) buffer_puts(buffer_1, "(Default.) No effect.\n"); else buffer_puts(buffer_1, "Oops! badmimetypes.cdb exists but badmimetypes doesn't.\n"); else if (stat("badmimetypes.cdb", &stmrhcdb) == -1) buffer_puts(buffer_1, "Oops! badmimetypes exists but badmimetypes.cdb doesn't.\n"); else if (stmrh.st_mtime > stmrhcdb.st_mtime) buffer_puts(buffer_1, "Oops! badmimetypes.cdb is older than badmimetypes.\n"); else buffer_puts(buffer_1, "Modified recently enough; hopefully up to date.\n"); do_lst("badrcptto", "Any RCPT TO is allowed.", "", " not accepted in RCPT TO."); do_str("bouncefrom", 0, "MAILER-DAEMON", "Bounce user name is "); do_str("bouncehost", 1, "bouncehost", "Bounce host name is "); do_int("bouncemaxbytes", "0", "Bounce size limit is ", " bytes"); do_int("concurrencylocal", "10", "Local concurrency is ", ""); do_int("concurrencyremote", "20", "Remote concurrency is ", ""); do_int("databytes", "0", "SMTP DATA limit is ", " bytes"); do_str("defaultdomain", 1, "defaultdomain", "Default domain name is "); do_str("defaulthost", 1, "defaulthost", "Default host name is "); do_lst("dkimdomains", "No DKIM domains defined for signing.", "DKIM domains: ", ""); do_lst("domaincerts", "No domain certs defined.", "Domain certs: ", ""); do_lst("domainips", "No domain ip mappings defined.", "Mappping sender domain part to local ip: ", ""); do_str("doublebouncehost", 1, "doublebouncehost", "2B recipient host: "); do_str("doublebounceto", 0, "postmaster", "2B recipient user: "); do_str("envnoathost", 1, "envnoathost", "Presumed domain name is "); do_str("helohost", 1, "helohost", "SMTP client HELO host name is "); do_str("idhost", 1, "idhost", "Message-ID host name is "); do_str("localiphost", 1, "localiphost", "Local IP address becomes "); do_lst("locals", "Messages for me are delivered locally.", "Messages for ", " are delivered locally."); do_str("me", 0, "undefined! Uh-oh", "My name is "); do_lst("mailfromrules", "Any envelope sender are accepted.", "", " (MAV rule)."); /* XXX: check mailfromrules.cdb contents */ buffer_puts(buffer_1, "\nmailfromrules.cdb: "); if (stat("mailfromrules", &stmrh) == -1) if (stat("mailfromrules.cdb", &stmrhcdb) == -1) buffer_puts(buffer_1, "(Default.) No effect.\n"); else buffer_puts(buffer_1, "Oops! mailfromrules.cdb exists but mailfromrules doesn't.\n"); else if (stat("mailfromrules.cdb", &stmrhcdb) == -1) buffer_puts(buffer_1, "Oops! mailfromrules exists but mailfromrules.cdb doesn't.\n"); else if (stmrh.st_mtime > stmrhcdb.st_mtime) buffer_puts(buffer_1, "Oops! mailfromrules.cdb is older than mailfromrules.\n"); else buffer_puts(buffer_1, "Modified recently enough; hopefully up to date.\n"); do_lst( "percenthack", "The percent hack is not allowed.", "The percent hack is allowed for user%host@", "."); do_str("plusdomain", 1, "plusdomain", "Plus domain name is "); do_lst("qmqpservers", "No QMQP servers.", "QMQP server: ", "."); do_int("queuelifetime", "604800", "Message lifetime in the queue is ", " seconds"); if (do_lst( "rcpthosts", "SMTP clients may send messages to any recipient.", "SMTP clients may send messages to recipients at ", ".")) do_lst("morercpthosts", "No effect.", "SMTP clients may send messages to recipients at ", "."); else do_lst( "morercpthosts", "No rcpthosts; morercpthosts is irrelevant.", "No rcpthosts; doesn't matter that morercpthosts has ", "."); /* XXX: check morercpthosts.cdb contents */ buffer_puts(buffer_1, "\nmorercpthosts.cdb: "); if (stat("morercpthosts", &stmrh) == -1) if (stat("morercpthosts.cdb", &stmrhcdb) == -1) buffer_puts(buffer_1, "(Default.) No effect.\n"); else buffer_puts(buffer_1, "Oops! morercpthosts.cdb exists but morercpthosts doesn't.\n"); else if (stat("morercpthosts.cdb", &stmrhcdb) == -1) buffer_puts(buffer_1, "Oops! morercpthosts exists but morercpthosts.cdb doesn't.\n"); else if (stmrh.st_mtime > stmrhcdb.st_mtime) buffer_puts(buffer_1, "Oops! morercpthosts.cdb is older than morercpthosts.\n"); else buffer_puts(buffer_1, "Modified recently enough; hopefully up to date.\n"); do_lst( "recipients", "SMTP clients may send messages to any recipient.", "SMTP clients may send messages to local recipients listed in ", "."); do_str("smtpgreeting", 1, "smtpgreeting", "SMTP greeting: 220 "); do_lst("qmtproutes", "No additional QMTP routes.", "QMTP route: ", ""); do_lst("smtproutes", "No artificial SMTP routes.", "SMTP route: ", ""); do_str("spfexplain", 0, SPF_DEFEXP, "SPF default explanation is: 550 "); do_str("spflocalrules", 0, "(None)", "Defined local SPF rules are: "); do_lst("srsrdomains", "No SRS fowarding rules.", "SRS rules: ", ""); do_int("timeoutconnect", "60", "SMTP client connection timeout is ", " seconds"); do_int("timeoutremote", "1200", "SMTP client data timeout is ", " seconds"); do_int("timeoutsmtpd", "1200", "SMTP server data timeout is ", " seconds"); do_lst("tlsdestinations", "No TLS destinations defined.", "TLS destination: ", ""); do_lst("virtualdomains", "No virtual domains.", "Virtual domain: ", ""); while ((d = readdir(dir))) { if (str_equal(d->d_name, ".")) continue; if (str_equal(d->d_name, "..")) continue; if (str_equal(d->d_name, "authsenders")) continue; if (str_equal(d->d_name, "badhelo")) continue; if (str_equal(d->d_name, "badrcptto")) continue; if (str_equal(d->d_name, "badmailfrom")) continue; if (str_equal(d->d_name, "badloadertypes")) continue; if (str_equal(d->d_name, "badloadertypes.cdb")) continue; if (str_equal(d->d_name, "badmimetypes")) continue; if (str_equal(d->d_name, "badmimetypes.cdb")) continue; if (str_equal(d->d_name, "bouncefrom")) continue; if (str_equal(d->d_name, "bouncehost")) continue; if (str_equal(d->d_name, "bouncemaxbytes")) continue; if (str_equal(d->d_name, "concurrencylocal")) continue; if (str_equal(d->d_name, "concurrencyremote")) continue; if (str_equal(d->d_name, "databytes")) continue; if (str_equal(d->d_name, "defaultdomain")) continue; if (str_equal(d->d_name, "defaulthost")) continue; if (str_equal(d->d_name, "dkimdomains")) continue; if (str_equal(d->d_name, "domainips")) continue; if (str_equal(d->d_name, "domaincerts")) continue; if (str_equal(d->d_name, "doublebouncehost")) continue; if (str_equal(d->d_name, "doublebounceto")) continue; if (str_equal(d->d_name, "envnoathost")) continue; if (str_equal(d->d_name, "helohost")) continue; if (str_equal(d->d_name, "idhost")) continue; if (str_equal(d->d_name, "localiphost")) continue; if (str_equal(d->d_name, "locals")) continue; if (str_equal(d->d_name, "me")) continue; if (str_equal(d->d_name, "mailfromrules")) continue; if (str_equal(d->d_name, "mailfromrules.cdb")) continue; if (str_equal(d->d_name, "morercpthosts")) continue; if (str_equal(d->d_name, "morercpthosts.cdb")) continue; if (str_equal(d->d_name, "percenthack")) continue; if (str_equal(d->d_name, "plusdomain")) continue; if (str_equal(d->d_name, "qmqpservers")) continue; if (str_equal(d->d_name, "queuelifetime")) continue; if (str_equal(d->d_name, "rcpthosts")) continue; if (str_equal(d->d_name, "recipients")) continue; if (str_equal(d->d_name, "smtpgreeting")) continue; if (str_equal(d->d_name, "qmtproutes")) continue; if (str_equal(d->d_name, "smtproutes")) continue; if (str_equal(d->d_name, "spfexplain")) continue; if (str_equal(d->d_name, "spflocalrules")) continue; if (str_equal(d->d_name, "srsdomains")) continue; if (str_equal(d->d_name, "timeoutconnect")) continue; if (str_equal(d->d_name, "timeoutremote")) continue; if (str_equal(d->d_name, "timeoutsmtpd")) continue; if (str_equal(d->d_name, "tlsdestinations")) continue; if (str_equal(d->d_name, "virtualdomains")) continue; buffer_puts(buffer_1, "\n"); buffer_puts(buffer_1, d->d_name); buffer_puts(buffer_1, ": I have no idea what this file does.\n"); } buffer_flush(buffer_1); _exit(0); }