Exemplo n.º 1
0
static int init(void)
{
  const char* tmp;

  if ((tmp = getprotoenv("LOCALHOST")) == 0) tmp = UNKNOWN;
  str_copys(&domain_name, tmp);

  if ((tmp = getenv("SMTPGREETING")) != 0)
    str_copys(&str_welcome, tmp);
  else {
    str_copy(&str_welcome, &domain_name);
    str_cats(&str_welcome, " mailfront");
  }
  str_cats(&str_welcome, " ESMTP");

  if ((tmp = getenv("MAXNOTIMPL")) != 0)
    maxnotimpl = strtoul(tmp, 0, 10);

  if (!str_cats(&init_capabilities, "8BITMIME\nENHANCEDSTATUSCODES\nPIPELINING")) {
    respond(&resp_oom);
    return 1;
  }

  return 0;
}
Exemplo n.º 2
0
/* actually do the log entry */
static void dosqlog(void)
{
  str sql;
  str mq, mr, md;
  unsigned int i, ni;

  if(!sqlseq) return;		/* nothing happened */

  str_init(&sql);
  str_init(&mq);
  str_init(&mr);
  str_init(&mflags);
  addflag("greylist", "greylist", 1);
  addflag("sump", "sump", 0);
  addflag("dblhelo", "dblhelo", 0);
  addflag("dblfrom", "dblfrom", 1);
  addflag("badrcpt", "badrcpt", 1);
  addflag("badbatv", "badbatv", 1);
  addflag("rcptrule", "badabuse", 1);

  str_copys(&sql, "update mail set flags='");
  str_cat(&sql, &mflags);
  sqlquote(&qsender, &mq);
  str_cats(&sql, "',mailfrom='");
  str_cat(&sql, &mq);
  /* envelope domain */
  i = str_findfirst(&qsender, '@');
  if(i < qsender.len) {
    str_init(&md);
    str_copyb(&md, qsender.s+i+1, qsender.len-i-1);
    sqlquote(&md, &mq);
    str_cats(&sql, "',envdomain='");
    str_cat(&sql, &mq);
  }
  str_cats(&sql, "' where serial=");
  str_cat(&sql, &sqlseqstr);
  sqlquery(&sql, 0);

  /* now add the recipients */
  for(i = 0; i < qrecips.len ; i = ni+1) {
    ni = str_findnext(&qrecips, 0, i);

    str_copyb(&mr, qrecips.s+i, ni-i);
    sqlquote(&mr, &mq);
    str_copys(&sql,"insert into mailrcpt(serial,rcptto) values(");
    str_cat(&sql, &sqlseqstr);
    str_cats(&sql, ",'");
    str_cat(&sql, &mq);
    str_cats(&sql, "')");
    sqlquery(&sql, 0);
  }
}
Exemplo n.º 3
0
static const response* message_end(int fd)
{
  struct stat st;
  char buf[1024];
  long rd;
  char* lf;
  char* ptr;

  if (fd >= 0) {
    /* Log the first two lines of the message, usually a Received: header */
    lseek(fd, 0, SEEK_SET);
    rd = read(fd, buf, sizeof buf - 1);
    buf[rd] = 0;
    if ((lf = strchr(buf, LF)) != 0) {
      str_copyb(&tmp, buf, lf-buf);
      ptr = lf + 1;
      if ((lf = strchr(ptr, LF)) != 0)
	str_catb(&tmp, ptr, lf-ptr);
      msg1(tmp.s);
    }

    fstat(fd, &st);
    databytes = st.st_size;
  }

  str_copys(&tmp, "Received ");
  str_catu(&tmp, databytes);
  str_cats(&tmp, " bytes.");
  resp.message = tmp.s;
  return &resp;
  (void)fd;
}
Exemplo n.º 4
0
int main(int argc, char* argv[])
{
  obuf bufout;
  obuf* out;
  const char* recipient;
  const char* sender;
  
  parse_args(argc, argv);

  if (opt_starttime && now < opt_starttime)
    ignore("Autoresponder is not active yet");
  if (opt_endtime && now > opt_endtime)
    ignore("Autoresponder is no longer active");

  recipient = getenv("RECIPIENT");
  if(!recipient)
    usage("RECIPIENT is not set, must be run from qmail.");
  sender = getenv("SENDER");
  if(!sender)
    usage("SENDER is not set, must be run from qmail.");
  
  check_sender(sender);

  str_copys(&subject, "Your mail");

  read_parse_headers();

  // Check rate that SENDER has sent
  if(!count_history(sender)) {
    log_sender(sender, 0);
    ignore("SENDER has sent too many messages");
  }

  if(opt_nosend)
    out = &outbuf;
  else {
    int msgfd = qmail_start();
    if (!obuf_init(&bufout, msgfd, 0, IOBUF_NEEDSCLOSE, 0))
      fail_temp("Could not initialize output buffer.");
    out = &bufout;
  }
  
  obuf_put3s(out, "To: <", sender, ">\n");
  if(opt_subject_prefix)
    obuf_put4s(out, "Subject: ", opt_subject_prefix, subject.s, "\n");
  if((!opt_no_inreplyto) && (message_id.len != 0))
    obuf_put3s(out, "In-Reply-To: ", message_id.s, "\n");

  build_response(out, sender, recipient);

  if (!obuf_close(out))
    fail_temp("Could not close output.");
  
  if (!opt_nosend)
    qmail_finish(sender);
  log_sender(sender, 1);
  
  return 0;
}
Exemplo n.º 5
0
void report_io_bytes(void)
{
  static str tmp;
  if (str_copys(&tmp, "bytes in: ") &&
      str_catu(&tmp, inbuf.io.offset) &&
      str_cats(&tmp, " bytes out: ") &&
      str_catu(&tmp, outbuf.io.offset))
    msg1(tmp.s);
}
Exemplo n.º 6
0
static const response* sender(str* s, str* params)
{
  str_copys(&tmp, "Sender='");
  str_cat(&tmp, s);
  str_cats(&tmp, "'.");
  str_cat_params(&tmp, params);
  resp.message = tmp.s;
  return &resp;
}
Exemplo n.º 7
0
static const response* recipient(str* r, str* params)
{
  str_copys(&tmp, "Recipient='");
  str_cat(&tmp, r);
  str_cats(&tmp, "'.");
  str_cat_params(&tmp, params);
  resp.message = tmp.s;
  return &resp;
}
Exemplo n.º 8
0
static void cmd_stat(void)
{
  if (!str_copys(&tmp, "+OK ") ||
      !str_catu(&tmp, msg_count - del_count) ||
      !str_catc(&tmp, SPACE) ||
      !str_catu(&tmp, msg_bytes - del_bytes))
    respond(err_internal);
  else
    respond(tmp.s);
}
Exemplo n.º 9
0
int open_file(const char* prefix, const char* filename)
{
  static str fullname;
  if (!str_truncate(&fullname, 0)) oom();
  if (prefix != 0) {
    if (!str_copys(&fullname, prefix)) oom();
    if (!str_catc(&fullname, '/')) oom();
  }
  if (!str_cats(&fullname, filename)) oom();
  return open(fullname.s, O_RDONLY);
}
Exemplo n.º 10
0
static void cmd_last(void)
{
  long last;
  long i;
  for (last = i = 0; i < msg_count; i++)
    if (msgs[i].read)
      last = i + 1;
  if (!str_copys(&tmp, "+OK ") ||
      !str_cati(&tmp, last))
    respond(err_internal);
  respond(tmp.s);
}
Exemplo n.º 11
0
static void cmd_list_one(const str* arg)
{
  long i;
  if ((i = msgnum(arg)) == 0) return;
  if (!str_copys(&tmp, "+OK ") ||
      !str_catu(&tmp, i) ||
      !str_catc(&tmp, SPACE) ||
      !str_catu(&tmp, msgs[i-1].size))
    respond(err_internal);
  else
    respond(tmp.s);
}
Exemplo n.º 12
0
/* ------------------------------------------------------------------------- */
const char* format_connection(const struct connections_entry* c)
{
  static str s;
  if (!str_copys(&s, ipv4_format(&c->key.ip))) return 0;
  if (!str_catc(&s, '/')) return 0;
  if (!str_catu(&s, c->key.port)) return 0;
  if (!str_catc(&s, '/')) return 0;
  if (!str_cat(&s, &c->data.service->key.sender)) return 0;
  if (!str_catc(&s, '/')) return 0;
  if (!str_cat(&s, &c->data.service->key.service)) return 0;
  if (!str_cats(&s, ": ")) return 0;
  return s.s;
}
Exemplo n.º 13
0
static void cmd_uidl_one(const str* arg)
{
  long i;
  if ((i = msgnum(arg)) != 0) {
    msg* m = &msgs[i-1];
    const char* fn = m->filename + 4;
    if (!str_copys(&tmp, "+OK ") ||
	!str_catu(&tmp, i) ||
	!str_catc(&tmp, SPACE) ||
	!str_catb(&tmp, fn, m->uid_len))
      respond(err_internal);
    else
      respond(tmp.s);
  }
}
Exemplo n.º 14
0
static void make_prq(void)
{
  brandom_fill(nonce, sizeof nonce);
  pkt_start(&packet, PRQ1);
  pkt_add_b(&packet, nonce, sizeof nonce);
  pkt_add_s1c(&packet, AUTHENTICATOR_NAME);
  wrap_str(str_copys(&keyex_name, nistp224_cb.name));
  if (keylist_get(&shared_secrets, &curve25519_cb) != 0) {
    wrap_str(str_catc(&keyex_name, 0));
    wrap_str(str_cats(&keyex_name, curve25519_cb.name));
  }
  pkt_add_s1(&packet, &keyex_name);
  pkt_add_s1c(&packet, KEYHASH_NAME);
  pkt_add_s1c(&packet, ENCRYPTOR_NAME);
  pkt_add_s1c(&packet, "null");
}
Exemplo n.º 15
0
/** Create a temporary file.

This function creates a temporary file by adding an difficult-to-predict
suffix (using the PID and microsecond timestamp) to the given prefix.
If this filename does not exist, it is opened in read/write mode.
*/
int path_mktemp(const char* prefix, str* filename)
{
  struct stat s;
  static long pid = 0;
  struct timeval tv;
  if (pid == 0)
    pid = getpid();
  do {
    if (!str_copys(filename, prefix)) return -1;
    if (!str_catc(filename, '.')) return -1;
    if (!str_catu(filename, pid)) return -1;
    gettimeofday(&tv, 0);
    if (!str_catc(filename, '.')) return -1;
    if (!str_catu(filename, tv.tv_sec)) return -1;
    if (!str_catc(filename, '.')) return -1;
    if (!str_catuw(filename, tv.tv_usec, 6, '0')) return -1;
  } while (lstat(filename->s, &s) != -1);
  return open(filename->s, O_RDWR | O_EXCL | O_CREAT, 0600);
}
Exemplo n.º 16
0
static void handle_packet(struct connection* c)
{
  str* packet;
  const char* id;
  const char* runas;
  const char* command;
  const char* envstart;
  long slot;
  unsigned int i;
  struct passwd* pw;

  packet = &c->packet;
  id = packet->s;
  if (*id == NUL)
    FAIL(id, "DInvalid ID");

  if ((slot = pick_slot()) < 0)
    FAIL(id, "DCould not allocate a slot");
  wrap_str(str_copys(&slots[slot].id, id));

  if ((i = str_findfirst(packet, NUL) + 1) >= packet->len)
    FAIL(id, "DInvalid packet");
  runas = packet->s + i;
  if (*runas == NUL
      || (pw = getpwnam(runas)) == 0)
    FAIL(id, "DInvalid username");

  if ((i = str_findnext(packet, NUL, i) + 1) >= packet->len)
    FAIL(id, "DInvalid packet");
  command = packet->s + i;

  if ((i = str_findnext(packet, NUL, i) + 1) >= packet->len)
    envstart = 0;
  else {
    envstart = packet->s + i;
    wrap_str(str_catc(packet, 0));
  }

  if (!init_slot(slot, pw))
    FAIL(id, "ZOut of memory");
  start_slot(slot, command, envstart);
}
Exemplo n.º 17
0
int check_rcpt(const char* sender)
{
  char* domain;
  
  if(!opt_checkrcpt)
    return 1;

  domain = strchr(sender, '@');
  if(!domain)
    return 0;

  for(++domain; domain; domain = strchr(domain+1, '.')) {
    if (!str_copys(&strbuf, domain)) oom();
    if (dict_get(&rcpthosts, &strbuf)) return 1;
    if (morercpthosts_fd != -1 &&
	cdb_find(&morercpthosts, strbuf.s, strbuf.len) != 0)
      return 1;
  }
  return 0;
}
Exemplo n.º 18
0
static void end_slot(int slot, int status)
{
  struct stat st;
  slots[slot].pid = 0;
  --slots_used;
  if (slots[slot].sending_email) {
    slots[slot].sending_email = 0;
    if (status)
      report_slot(slot, "ZJob complete, sending email failed");
    else
      report_slot(slot, "KJob complete, email sent");
  }
  else {
    /* No header, no possible way to send email. */
    if (slots[slot].headerlen == 0)
      report_slot(slot, "KJob complete, no MAILTO");
    else {
      /* If the job crashed, make sure it is noted. */
      if (WIFSIGNALED(status)) {
	debugf(DEBUG_EXEC, "{slot }d{ Job was killed by signal #}d",
	       slot, WTERMSIG(status));
	wrap_str(str_copys(&tmp, "\n\nJob was killed by signal #"));
	wrap_str(str_cati(&tmp, WTERMSIG(status)));
	wrap_str(str_catc(&tmp, '\n'));
	write(slots[slot].tmpfd, tmp.s, tmp.len);
      }
      if (fstat(slots[slot].tmpfd, &st) == -1)
	failsys_slot(slot, "ZCould not fstat");
      else if (st.st_size > slots[slot].headerlen)
	send_email(slot);
      else
	report_slot(slot, "KJob complete, no mail sent");
    }
    /* To simplify the procedure, close the temporary file early.
     * The email sender still has it open, and will effect the final
     * deletion of the file when it completes. */
    if (slots[slot].tmpfd != devnull)
      close(slots[slot].tmpfd);
    slots[slot].tmpfd = -1;
  }
}
Exemplo n.º 19
0
/** Qualify a domain name through DNS requests.

    This function is used to qualify what may be a partial domain name
    into a fully qualified domain name through a set of rules and a
    resolver function. The resolution rules are read by \c
    dns_resolvconfrewrite. For each possible qualification of the domain
    name, the resolver function is called to test if the qualified
    domain name exists.

    \param out Output storage for the DNS record results.
    \param fqdn Output storage for the fully qualified domain name.
    \param rules The list of rules to use to qualify the domain name.
    \param in Domain name (full or partial) to qualify.
    \param fn Function to call (such as \c dns_ip4) to determine if a
    qualified domain name exists.
*/
int dns_qualify_rules(struct dns_result* out, str *fqdn, const char *in, const str *rules,
		      int (*fn)(struct dns_transmit*, struct dns_result*, const char*))
{
  unsigned int i;
  unsigned int j;
  unsigned int plus;
  unsigned int fqdnlen;
  const char *p;
  struct dns_transmit tx;

  if (!str_copys(fqdn,in)) return -1;
  memset(&tx, 0, sizeof tx);

  for (j = i = 0;j < rules->len;++j)
    if (!rules->s[j]) {
      if (!doit(fqdn,rules->s + i)) return -1;
      i = j + 1;
    }

  fqdnlen = fqdn->len;
  p = memchr(fqdn->s,'+',fqdnlen);
  if (!p)
    return fn(&tx,out,fqdn->s);
  plus = p - fqdn->s;

  i = plus + 1;
  for (;;) {
    p = memchr(fqdn->s + i,'+',fqdnlen - i);
    j = p ? p - (fqdn->s + i) : fqdnlen - i;
    memmove(fqdn->s + plus,fqdn->s + i,j);
    if (!str_truncate(fqdn, plus + j)) return -1;
    if (fn(&tx,out,fqdn->s) == -1) return -1;
    if (out->count) return 0;
    i += j;
    if (i >= fqdnlen) return 0;
    ++i;
  }
}
Exemplo n.º 20
0
static void cmd_quit(void)
{
  long i;
  for (i = 0; i < msg_count; i++) {
    const char* fn = msgs[i].filename;
    if (msgs[i].deleted)
      unlink(fn);
    /* Logic: 
     * 1. move all messages into "cur"
     * 2. tag all read messages without flags with a read flag (:2,S)
     * Note: no real opportunity to report errors,
     * so just continue when we hit one.
     */
    else {
      if (!str_copys(&tmp, "cur/")) continue;
      if (!str_cats(&tmp, fn+4)) continue;
      if (msgs[i].read && !add_flag(&tmp, 'S')) continue;
      rename(fn, tmp.s);
    }
  }
  respond(ok);
  exit(0);
}
Exemplo n.º 21
0
static int setup_env(void)
{
  const char* s;
  const char* colon;
  struct stat st;

  if (cvm_fact_mailbox != 0
      && (s = getenv("SETUP_ENV")) != 0
      && strcmp(s, "dovecot") == 0) {
    /* This tells Dovecot that its environment has already been set up. */
    if (putenv("DOVECONF_ENV=1") != 0)
      return 0;
    /* Use the file type to set the prefix to mbox: or maildir:
     * Assume missing files are mboxes. */
    s = (stat(cvm_fact_mailbox, &st) == 0
	 && S_ISDIR(st.st_mode))
      ? "maildir:"
      : "mbox:";
    /* Use cmd for temporary storage of the substituted mailbox name */
    if (!str_copys(&cmd, s))
      return 0;
    s = cvm_fact_mailbox;
    while ((colon = strchr(s, ':')) != 0) {
      if (!str_catb(&cmd, s, colon-s)
	  || !str_catb(&cmd, "::", 2))
	return 0;
      s = colon + 1;
    }
    if (!str_cats(&cmd, s))
      return 0;
    cvm_fact_mailbox = cmd.s;
  }
  return cvm_setenv()
    && setenv("IMAPLOGINTAG", tag.s, 1) == 0
    && setenv("AUTHENTICATED", cvm_fact_username, 1) == 0;
}
Exemplo n.º 22
0
static long scan_dir(const char* subdir, str* list, long* countptr, long max)
{
  DIR* dir;
  direntry* entry;
  long count;
  
  if ((dir = opendir(subdir)) == 0) return 0;
  count = 0;
  while (!(max_count > 0 && msg_count >= max_count) &&
	 !(max > 0 && count >= max) &&
	 (entry = readdir(dir)) != 0) {
    if (entry->d_name[0] == '.') continue;
    if (!str_copys(&tmp, subdir)) return 0;
    if (!str_catc(&tmp, '/')) return 0;
    if (!str_cats(&tmp, entry->d_name)) return 0;
    if (!str_cat(list, &tmp)) return 0;
    if (!str_catc(list, 0)) return 0;
    ++count;
    ++msg_count;
  }
  closedir(dir);
  *countptr = count;
  return 1;
}
Exemplo n.º 23
0
int startup(int argc, char* argv[])
{
  const char* tmp;
  const char* end;
  const char* cwdstr;
  char* ptr;
  unsigned long session_timeout;
  unsigned startup_code;

  if ((tmp = getenv("TCPLOCALIP")) == 0) FAIL("Missing $TCPLOCALIP.");
  if (!parse_localip(tmp)) FAIL("Could not parse $TCPLOCALIP.");
  if ((tmp = getenv("TCPREMOTEIP")) == 0) FAIL("Missing $TCPREMOTEIP.");
  if (!parse_remoteip(tmp)) FAIL("Could not parse $TCPREMOTEIP.");
  if ((tmp = getenv("UID")) == 0) FAIL("Missing $UID.");
  if (!(uid = strtou(tmp, &end)) || *end) FAIL("Invalid $UID.");
  if ((tmp = getenv("GID")) == 0) FAIL("Missing $GID.");
  if (!(gid = strtou(tmp, &end)) || *end) FAIL("Invalid $GID.");
  if ((home = getenv("HOME")) == 0) FAIL("Missing $HOME.");
  if ((tmp = getenv("GIDS")) != 0 && !parse_gids(tmp))
    FAIL("Could not parse or set supplementary group IDs.");

  /* Strip off trailing slashes in $HOME */
  ptr = (char*)home + strlen(home)-1;
  while (ptr > home && *ptr == '/') *ptr-- = 0;

  if ((user = getenv("USER")) == 0) FAIL("Missing $USER.");
  if ((group = getenv("GROUP")) == 0) group = "mygroup";
  if (chdir(home)) FAIL("Could not chdir to $HOME.");
  if (!load_tables()) FAIL("Loading startup tables failed.");
  if (getenv("CHROOT") != 0) {
    cwdstr = "/";
    if (chroot(".")) FAIL("Could not chroot.");
  }
  else if (getenv("SOFTCHROOT") != 0) {
    cwdstr = "/";
  }
  else {
    cwdstr = home;
    if (chdir("/")) FAIL("Could not chdir to '/'.");
  }
  if (!str_copys(&cwd, cwdstr)) FAIL("Could not set CWD string");
  if (setgid(gid)) FAIL("Could not set GID.");
  if (setuid(uid)) FAIL("Could not set UID.");
  if ((user_len = strlen(user)) > MAX_NAME_LEN) {
    user_len = MAX_NAME_LEN;
    ((char*)user)[MAX_NAME_LEN] = 0;
  }
  if ((group_len = strlen(group)) > MAX_NAME_LEN) {
    group_len = MAX_NAME_LEN;
    ((char*)group)[MAX_NAME_LEN] = 0;
  }

  lockhome = (getenv("LOCKHOME") != 0);
  nodotfiles = (getenv("NODOTFILES") != 0);
  list_options = (nodotfiles ? 0 : PATH_MATCH_DOTFILES);

  session_timeout = 0;
  if ((tmp = getenv("SESSION_TIMEOUT")) != 0)
    session_timeout = strtou(tmp, &tmp);
  alarm(session_timeout);
  connect_timeout = timeout;
  if ((tmp = getenv("CONNECT_TIMEOUT")) != 0)
    connect_timeout = strtou(tmp, &tmp);

  if ((tmp = getenv("TWOFTPD_BIND_PORT_FD")) != 0) {
    if ((bind_port_fd = strtou(tmp, &end)) == 0 || *end != 0)
      FAIL("Invalid $TWOFTPD_BIND_PORT_FD");
  }
  else
    bind_port_fd = -1;

  startup_code = (getenv("AUTHENTICATED") != 0) ? 230 : 220;
  if ((tmp = getenv("BANNER")) != 0) show_banner(startup_code, tmp);
  message_file = getenv("MESSAGEFILE");
  show_message_file(startup_code);
  return respond(startup_code, 1, "Ready to transfer files.");
  (void)argc;
  (void)argv;
}