コード例 #1
0
ファイル: protocol-smtp.c プロジェクト: cweimann/mailfront
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;
}
コード例 #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);
  }
}
コード例 #3
0
ファイル: backend-echo.c プロジェクト: ser/mailfront
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;
}
コード例 #4
0
ファイル: main.c プロジェクト: bruceg/qmail-autoresponder
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;
}
コード例 #5
0
ファイル: iobytes.c プロジェクト: bruceg/mailfront
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);
}
コード例 #6
0
ファイル: backend-echo.c プロジェクト: ser/mailfront
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;
}
コード例 #7
0
ファイル: backend-echo.c プロジェクト: ser/mailfront
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;
}
コード例 #8
0
ファイル: pop3front-maildir.c プロジェクト: bruceg/mailfront
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);
}
コード例 #9
0
ファイル: openread.c プロジェクト: bruceg/qmail-notify
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);
}
コード例 #10
0
ファイル: pop3front-maildir.c プロジェクト: bruceg/mailfront
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);
}
コード例 #11
0
ファイル: pop3front-maildir.c プロジェクト: bruceg/mailfront
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);
}
コード例 #12
0
ファイル: connections.c プロジェクト: bruceg/srlog2
/* ------------------------------------------------------------------------- */
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;
}
コード例 #13
0
ファイル: pop3front-maildir.c プロジェクト: bruceg/mailfront
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);
  }
}
コード例 #14
0
ファイル: srlog2.c プロジェクト: bruceg/srlog2
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");
}
コード例 #15
0
ファイル: mktemp.c プロジェクト: bruceg/bglibs
/** 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);
}
コード例 #16
0
ファイル: bcron-exec.c プロジェクト: 0xef53/bcron
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);
}
コード例 #17
0
ファイル: qmail-notify.c プロジェクト: bruceg/qmail-notify
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;
}
コード例 #18
0
ファイル: bcron-exec.c プロジェクト: 0xef53/bcron
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;
  }
}
コード例 #19
0
ファイル: dns_qualify.c プロジェクト: bruceg/bglibs
/** 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;
  }
}
コード例 #20
0
ファイル: pop3front-maildir.c プロジェクト: bruceg/mailfront
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);
}
コード例 #21
0
ファイル: imapfront-auth.c プロジェクト: bruceg/mailfront
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;
}
コード例 #22
0
ファイル: pop3front-maildir.c プロジェクト: bruceg/mailfront
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;
}
コード例 #23
0
ファイル: backend.c プロジェクト: bruceg/twoftpd
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;
}