Beispiel #1
0
static int
enable_service (const char *name, intptr_t from_next)
{
    int offset;
    int r;
    int i;

    if (*name == '/')
        cur_name = name + byte_rchr (name, strlen (name), '/') + 1;
    else
        cur_name = name;

    if (!from_next)
    {
        /* check if it was already added to be done next (via auto-enable), in
         * which case we need to remove it.
         * We do this instead of simply skipping it and having it done later
         * because:
         * - if there's a folder here, we want to use it as config folder
         * - in upgrade mode, the auto-added are treated differently, so
         *   anything specified needs to be treated now (even w/out folder)
         */
        for (i = 0; i < genalloc_len (int, &ga_next); ++i)
            if (str_equal (cur_name, names.s + list_get (&ga_next, i)))
            {
                offset = list_get (&ga_next, i);
                ga_remove (int, &ga_next, i);
                goto process;
            }

        offset = names.len;
        stralloc_catb (&names, cur_name, strlen (cur_name) + 1);
    }
Beispiel #2
0
void mkauthhash(const char *s,unsigned int len,char *h)
/* This is a string that should be the same for all messages from a given   */
/* author. Doesn't have to be the real rfc822 address. We look for a '@'    */
/* and grab everything up to the next '>', ' ', or ';'. We go back the same */
/* way, then take everything up to the '@' or the first '-'. The latter     */
/* avoids problems with posters that band their addresses.                  */
{
  unsigned int i,j,k,l;
  char ch;

  j = k = l = 0;
  i = byte_rchr(s,len,'@');
  if (i < len) {		/* if not then i=sa->len, j=k=l=0 */
    j = i;
    while (++j < len) {		/* if not found, then j=sa->len */
      ch = s[j];
      if (ch == '>' || ch == ' ' || ch == ';') break;
    }
    k = i;
    while (k > 0) {		/* k <= i */
      ch = s[--k];
      if (ch == '<' || ch == ' ' || ch == ';') break;
    }
    l = k;			/* k <= l <= i; */
    while (l < i && s[l] != '-') ++l;
    if (!stralloc_copyb(&dummy,s + k, l - k)) die_nomem();
    if (!stralloc_catb(&dummy,s + i, j - i)) die_nomem();
    makehash(dummy.s,dummy.len,h);
  } else			/* use entire line if no '@' found */
    makehash(s,len,h);
}
Beispiel #3
0
int c_write(int pos,char *buf,int len)
{
  struct cyclog *d;
  int w;

  d = c + pos;

  if (d->bytes >= d->size)
    fullcurrent(d);

  if (len >= d->size - d->bytes)
    len = d->size - d->bytes;

  if (d->bytes + len >= d->size - 2000) {
    w = byte_rchr(buf,len,'\n');
    if (w < len)
      len = w + 1;
  }

  for (;;) {
    w = write(d->fdcurrent,buf,len);
    if (w > 0) break;
    pause3("unable to write to ",d->dir,"/current, pausing: ");
  }

  d->bytes += w;
  if (d->bytes >= d->size - 2000)
    if (buf[w - 1] == '\n')
      fullcurrent(d);

  return w;
}
Beispiel #4
0
static int _issub(struct subdbinfo *info,
                  const char *table,
                  const char *userhost,
                  stralloc *recorded)
{
    sqlite3_stmt *stmt;
    unsigned int j;
    int res;

    /* SELECT address FROM list WHERE address = 'userhost' AND hash */
    /* BETWEEN 0 AND 52. Without the hash restriction, we'd make it */
    /* even easier to defeat. Just faking sender to the list name would*/
    /* work. Since sender checks for posts are bogus anyway, I don't */
    /* know if it's worth the cost of the "WHERE ...". */

    if (!stralloc_copys(&addr,userhost)) die_nomem();
    j = byte_rchr(addr.s,addr.len,'@');
    if (j == addr.len) return 0;
    case_lowerb(addr.s + j + 1,addr.len - j - 1);

    if (!stralloc_copys(&line,"SELECT address FROM ")) die_nomem();
    if (!stralloc_cat_table(&line,info,table)) die_nomem();
    if (!stralloc_cats(&line," WHERE address LIKE '")) die_nomem();
    if (!stralloc_cat(&line,&addr)) die_nomem();
    if (!stralloc_cats(&line,"'")) die_nomem();
    if (!stralloc_0(&line)) die_nomem();

    if ((stmt = _sqlquery(info, &line)) == NULL)	/* select */
        strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn));

    /* No data returned in QUERY */
    res = sqlite3_step(stmt);
    if (res != SQLITE_ROW)
    {
        if (res != SQLITE_DONE)
            strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn));

        sqlite3_finalize(stmt);
        return 0;
    }

    if (recorded)
    {
        if (!stralloc_copyb(recorded, (const char*)sqlite3_column_text(stmt, 0), sqlite3_column_bytes(stmt, 0)))
            die_nomem();
        if (!stralloc_0(recorded)) die_nomem();
    }

    sqlite3_finalize(stmt);
    return 1;
}
Beispiel #5
0
int sub_sql_issub(struct subdbinfo *info,
		  const char *table,
		  const char *userhost,
		  stralloc *recorded)
{
  unsigned int j;
  void *result;
  int ret;

  /* SELECT address FROM list WHERE address = 'userhost' AND hash */
  /* BETWEEN 0 AND 52. Without the hash restriction, we'd make it */
  /* even easier to defeat. Just faking sender to the list name would*/
  /* work. Since sender checks for posts are bogus anyway, I don't */
  /* know if it's worth the cost of the "WHERE ...". */

  make_name(info,table?"_":0,table,0);

  /* Lower-case the domain portion */
  stralloc_copys(&addr,userhost);
  j = byte_rchr(addr.s,addr.len,'@');
  if (j == addr.len)
    return 0;
  case_lowerb(addr.s + j + 1,addr.len - j - 1);

  stralloc_copys(&query,"SELECT address FROM ");
  stralloc_cat(&query,&name);
  stralloc_cats(&query," WHERE ");
  stralloc_cats(&query,sql_issub_where_defn);

  result = sql_select(info,&query,1,&addr);

  if (!sql_fetch_row(info,result,1,&addr))
    ret = 0;
  else {
    /* we need to return the actual address as other dbs may accept
     * user-*@host, but we still want to make sure to send to e.g the
     * correct moderator address. */
    if (recorded != 0) {
      stralloc_copy(recorded,&addr);
      stralloc_0(recorded);
    }
    ret = 1;
  }
  sql_free_result(info,result);
  return ret;
}
Beispiel #6
0
void maketo(void)
/* expects line to be a return-path line. If it is and the format is valid */
/* to is set to to the sender. Otherwise, to is left untouched. Assuming   */
/* to is empty to start with, it will remain empty if no sender is found.  */
{
  unsigned int x, y;

    if (case_startb(line.s,line.len,"return-path:")) {
      x = 12 + byte_chr(line.s + 12,line.len-12,'<');
      if (x != line.len) {
        y = byte_rchr(line.s + x,line.len-x,'>');
        if (y + x != line.len) {
          if (!stralloc_copyb(&to,line.s+x+1,y-1)) die_nomem();
          if (!stralloc_0(&to)) die_nomem();
        }		/* no return path-> no addressee. A NUL in the sender */
      }			/* is no worse than a faked sender, so no problem */
    }
}
Beispiel #7
0
int std_subscribe(const char *dir,
		  const char *subdir,
		  const char *userhost,
		  int flagadd,
		  const char *comment,
		  const char *event,
		  int forcehash)
/* add (flagadd=1) or remove (flagadd=0) userhost from the subscr. database  */
/* dbname. Comment is e.g. the subscriber from line or name. It is added to  */
/* the log. Event is the action type, e.g. "probe", "manual", etc. The       */
/* direction (sub/unsub) is inferred from flagadd. Returns 1 on success, 0   */
/* on failure. If flagmysql is set and the file "sql" is found in the        */
/* directory dbname, it is parsed and a mysql db is assumed. if forcehash is */
/* >=0 it is used in place of the calculated hash. This makes it possible to */
/* add addresses with a hash that does not exist. forcehash has to be 0..99. */
/* for unsubscribes, the address is only removed if forcehash matches the    */
/* actual hash. This way, ezmlm-manage can be prevented from touching certain*/
/* addresses that can only be removed by ezmlm-unsub. Usually, this would be */
/* used for sublist addresses (to avoid removal) and sublist aliases (to     */
/* prevent users from subscribing them (although the cookie mechanism would  */
/* prevent the resulting duplicate message from being distributed. */
{
  int fdlock;

  unsigned int j;
  unsigned char ch,lcch;
  int match;
  int flagwasthere;

  if (userhost[str_chr(userhost,'\n')])
    strerr_die2x(100,FATAL,ERR_ADDR_NL);

    if (!stralloc_copys(&addr,"T")) die_nomem();
    if (!stralloc_cats(&addr,userhost)) die_nomem();
    if (addr.len > 401)
      strerr_die2x(100,FATAL,ERR_ADDR_LONG);

    j = byte_rchr(addr.s,addr.len,'@');
    if (j == addr.len)
      strerr_die2x(100,FATAL,ERR_ADDR_AT);
    case_lowerb(addr.s + j + 1,addr.len - j - 1);
    if (!stralloc_copy(&lcaddr,&addr)) die_nomem();
    case_lowerb(lcaddr.s + 1,j - 1);	/* make all-lc version of address */

    if (forcehash >= 0 && forcehash <= 52) {
      ch = lcch = 64 + (unsigned char) forcehash;
    } else {
      ch = 64 + subhashsa(&addr);
      lcch = 64 + subhashsa(&lcaddr);
    }

    if (!stralloc_0(&addr)) die_nomem();
    if (!stralloc_0(&lcaddr)) die_nomem();
    std_makepath(&fn,dir,subdir,"/subscribers/",lcch);
    std_makepath(&fnlock,dir,subdir,"/lock",0);

    if (!stralloc_copyb(&fnnew,fn.s,fn.len-1)) die_nomem();
	/* code later depends on fnnew = fn + 'n' */
    if (!stralloc_cats(&fnnew,"n")) die_nomem();
    if (!stralloc_0(&fnnew)) die_nomem();

    fdlock = lockfile(fnlock.s);

				/* do lower case hashed version first */
    fdnew = open_trunc(fnnew.s);
    if (fdnew == -1) die_write();
    substdio_fdbuf(&ssnew,write,fdnew,ssnewbuf,sizeof(ssnewbuf));

    flagwasthere = 0;

    fd = open_read(fn.s);
    if (fd == -1) {
      if (errno != error_noent) { close(fdnew); die_read(); }
    }
    else {
      substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf));

      for (;;) {
        if (getln(&ss,&line,&match,'\0') == -1) {
	  close(fd); close(fdnew); die_read();
        }
        if (!match) break;
        if (line.len == addr.len)
          if (!case_diffb(line.s,line.len,addr.s)) {
	    flagwasthere = 1;
	    if (!flagadd)
	      continue;
	  }
        if (substdio_bput(&ssnew,line.s,line.len) == -1) {
	  close(fd); close(fdnew); die_write();
        }
      }

      close(fd);
    }

    if (flagadd && !flagwasthere)
      if (substdio_bput(&ssnew,addr.s,addr.len) == -1) {
        close(fdnew); die_write();
      }

    if (substdio_flush(&ssnew) == -1) { close(fdnew); die_write(); }
    if (fsync(fdnew) == -1) { close(fdnew); die_write(); }
    close(fdnew);

    if (rename(fnnew.s,fn.s) == -1)
      strerr_die6sys(111,FATAL,ERR_MOVE,fnnew.s," to ",fn.s,": ");

    if ((ch == lcch) || flagwasthere) {
      close(fdlock);
      if (flagadd ^ flagwasthere) {
        if (!stralloc_0(&addr)) die_nomem();
        logaddr(dir,subdir,event,addr.s+1,comment);
        return 1;
      }
      return 0;
    }

			/* If unsub and not found and hashed differ, OR */
			/* sub and not found (so added with new hash) */
			/* do the 'case-dependent' hash */

    fn.s[fn.len - 2] = ch;
    fnnew.s[fnnew.len - 3] = ch;
    fdnew = open_trunc(fnnew.s);
    if (fdnew == -1) die_write();
    substdio_fdbuf(&ssnew,write,fdnew,ssnewbuf,sizeof(ssnewbuf));

    fd = open_read(fn.s);
    if (fd == -1) {
      if (errno != error_noent) { close(fdnew); die_read(); }
    } else {
      substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf));

      for (;;) {
        if (getln(&ss,&line,&match,'\0') == -1)
          { close(fd); close(fdnew); die_read(); }
        if (!match) break;
        if (line.len == addr.len)
          if (!case_diffb(line.s,line.len,addr.s)) {
            flagwasthere = 1;
            continue;	/* always want to remove from case-sensitive hash */
          }
        if (substdio_bput(&ssnew,line.s,line.len) == -1)
          { close(fd); close(fdnew); die_write(); }
      }

      close(fd);
    }

    if (substdio_flush(&ssnew) == -1) { close(fdnew); die_write(); }
    if (fsync(fdnew) == -1) { close(fdnew); die_write(); }
    close(fdnew);

    if (rename(fnnew.s,fn.s) == -1)
      strerr_die6sys(111,FATAL,ERR_MOVE,fnnew.s," to ",fn.s,": ");

    close(fdlock);
    if (flagadd ^ flagwasthere) {
      if (!stralloc_0(&addr)) die_nomem();
      logaddr(dir,subdir,event,addr.s+1,comment);
      return 1;
    }
    return 0;

}
int main(int argc,char **argv)
{
  char *action;
  const char *err;
  unsigned int i;
  int act = AC_NONE;	/* desired action */
  unsigned int actlen = 0;/* str_len of above */

  (void) umask(022);
  sig_pipeignore();
  when = now();

  getconfopt(argc,argv,options,1,&dir);
  initsub(0);

  sender = get_sender();
  if (!sender) die_sender();
  action = env_get("DEFAULT");
  if (!action) strerr_die2x(100,FATAL,MSG(ERR_NODEFAULT));

  if (!*sender)
    strerr_die2x(100,FATAL,MSG(ERR_BOUNCE));
  if (!sender[str_chr(sender,'@')])
    strerr_die2x(100,FATAL,MSG(ERR_ANONYMOUS));
  if (str_equal(sender,"#@[]"))
    strerr_die2x(100,FATAL,MSG(ERR_BOUNCE));

  action = set_workdir(action);

  stralloc_copys(&target,sender);
  if (action[0]) {
    i = str_chr(action,'-');
    if (action[i]) {
      action[i] = 0;
      stralloc_copys(&target,action + i + 1);
      i = byte_rchr(target.s,target.len,'=');
      if (i < target.len)
	target.s[i] = '@';
    }
  }
  stralloc_0(&target);
  set_cptarget(target.s);	/* for copy() */
  make_verptarget();

  act = get_act_ismod(action,&actlen);

  stralloc_copy(&from,&outlocal);
  stralloc_cats(&from,"-return-@");
  stralloc_cat(&from,&outhost);
  stralloc_0(&from);

  if (qmail_open(&qq) == -1)
    strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE));
  msg_headers(act);

  if (act == AC_SUBSCRIBE)
    do_subscribe(action);
  else if (act == AC_SC)
    do_sc(action);
  else if (str_start(action,ACTION_RC))
    do_rc_tc(action,ACTION_RC);
  else if(str_start(action,ACTION_TC))
    do_rc_tc(action,ACTION_TC);
  else if (act == AC_UNSUBSCRIBE)
    do_unsubscribe(action);
  else if (str_start(action,ACTION_UC))
    do_uc(action);
  else if (str_start(action,ACTION_VC))
    do_vc_wc(action,ACTION_VC);
  else if (str_start(action,ACTION_WC))
    do_vc_wc(action,ACTION_WC);
  else if (act == AC_LIST || act == AC_LISTN) 
    do_list(act);
  else if (act == AC_LOG)
    do_log(action,actlen);
  else if (act == AC_EDIT)
    do_edit(action);
  else if (str_start(action,ACTION_ED))
    do_ed(action);
  else if (act == AC_GET)
    do_get(action);
  else if (case_starts(action,ACTION_QUERY) ||
		case_starts(action,ALT_QUERY))
    do_query();
  else if (case_starts(action,ACTION_INFO) ||
		case_starts(action,ALT_INFO))
    do_info();
  else if (case_starts(action,ACTION_FAQ) ||
		case_starts(action,ALT_FAQ))
    do_faq();
  else if (ismod && (act == AC_HELP))
    do_mod_help();
  else
    do_help();

  err = qmail_close(&qq);
  closesub();
  if (*err != '\0')
    strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1);
  strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0;
  strerr_die3x(0,INFO,"qp ",strnum);
}
Beispiel #9
0
int
main(int argc, char **argv)
{
	int match;
	unsigned int at;

	log_init(STDERR, ~256, 0);

	if (read_controls(ctrls) == -1)
		die_control();
	
	q = 0;
	do {
		if (getln(&ssin, &line, &match, '\0') != 0) {
			if (errno != error_timeout)
				die_read();
			cleanup();
			continue;
		}
		if (!match) {
			cleanup(); /* other side closed pipe */
			break;
		}

		logit(32, "qmail-verfiy: verifying %S\n", &line);

		at = byte_rchr(line.s,line.len,'@');
		if (at >= line.len) {
			if (substdio_puts(subfdout, "DSorry, address must "
			    "include host name. (#5.1.3)") == -1)
				die_write();
			if (substdio_putflush(subfdout, "", 1) == -1)
				die_write();
			continue;
		}

		switch (lookup(&line)) {
		case 0:
			if (localdelivery()) {
				/*
				 * Do the local address lookup.
				 */
				line.s[at] = '\0';
				if (lookup_cdb(line.s) == 1)
					break;
				if (lookup_passwd(line.s) == 1)
					break;
			}
			/* Sorry, no mailbox here by that name. */
			if (substdio_puts(subfdout,
			    "DSorry, no mailbox here by that name. "
			    "(#5.1.1)") == -1)
				die_write();
			if (substdio_putflush(subfdout, "", 1) == -1)
				die_write();
			break;
		case 1:
		default:
			break;
		}
	} while (1);

	return 0;
}
Beispiel #10
0
int main(int argc,char **argv)
{
  int child;
  const char *sendargs[4];
  stralloc addr = {0};
  unsigned int pos = 0,pos2,poslocal,len;
  const char *cp;

  unsigned long hh = 4L;		/* default time 04:12 */
  unsigned long mm = 12L;
  const char *dow = "*";		/* day of week */
  const char *qmail_inject = "/bin/qmail-inject ";
  char strnum[FMT_ULONG];
  unsigned long uid,euid = 0;

  stralloc rp = {0};
  stralloc user = {0};
  stralloc euser = {0};
  stralloc dir = {0};
  stralloc listaddr = {0};
  stralloc line = {0};

  struct passwd *ppasswd;

  int match;
  int hostmatch;
  int localmatch;
  unsigned long dh,t;
  int founduser = 0;
  int listmatch = 0;
  int flagdigit = 0;
  int flagours;
  int foundlocal = 0;
  int foundmatch = 0;
  unsigned int nolists = 0;
  unsigned long maxlists;
  unsigned int lenhost,lenlocal;
  int fdin,fdout = -1;

  char *local = (char *) 0;	/* list = local@host */
  const char *host = (char *) 0;
  char *code = (char *) 0;	/* digest code */

  char inbuf[512];
  substdio ssin;

  char outbuf[512];
  substdio ssout;

  (void) umask(077);
  sig_pipeignore();

  optind = getconfopt(argc,argv,options,0,0);
  if (flagt != 0) {
    pos = scan_ulong(flagt,&hh);
    if (flagt[pos++] != ':') die_usage();
    (void) scan_ulong(flagt + pos,&mm);
  }
  if (flagw != 0) {
    dow = flagw;
    cp = flagw - 1;
    while (*(++cp)) {
      if (*cp >= '0' && *cp <= '7') {
	if (flagdigit) die_dow();
	flagdigit = 1;
      } else if (*cp == ',') {
	if (!flagdigit) die_dow();
	flagdigit = 0;
      } else
	die_dow();
    }
  }

  if (flaglist + flagdelete + flagconfig > 1)
    strerr_die2x(100,FATAL,MSG(ERR_EXCLUSIVE));
  uid = getuid();
  if (uid && !(euid = geteuid()))
    strerr_die2x(100,FATAL,MSG(ERR_SUID));
  if (!(ppasswd = getpwuid(uid)))
    strerr_die2x(100,FATAL,MSG(ERR_UID));
  if (!stralloc_copys(&user,ppasswd->pw_name)) die_nomem();
  if (!stralloc_0(&user)) die_nomem();
  if (!(ppasswd = getpwuid(euid)))
    strerr_die2x(100,FATAL,MSG(ERR_EUID));
  if (!stralloc_copys(&dir,ppasswd->pw_dir)) die_nomem();
  if (!stralloc_0(&dir)) die_nomem();
  if (!stralloc_copys(&euser,ppasswd->pw_name)) die_nomem();
  if (!stralloc_0(&euser)) die_nomem();

  wrap_chdir(dir.s);

  local = argv[optind++];	/* list address, optional for -c & -l */
  if (!local) {
    if (!flagconfig && !flaglist)
      die_usage();
    lenlocal = 0;
    lenhost = 0;
  } else {
    if (!stralloc_copys(&listaddr,local)) die_nomem();
    if (!isclean(local,1))
      die_argument();
    pos = str_chr(local,'@');
    lenlocal = pos;
    local[pos] = '\0';
    host = local + pos + 1;
    lenhost = str_len(host);
    code = argv[optind];
    if (!code) {		/* ignored for -l, -c, and -d */
      if (flagdelete || flaglist || flagconfig)
				/* get away with not putting code for delete */
        code = (char*)"a";	/* a hack - so what! */
      else
        die_usage();
    } else
      if (!isclean(code,0))
        die_argument();
  }
  if ((fdin = open_read(TXT_EZCRONRC)) == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,TXT_EZCRONRC));
	/* first line is special */
  substdio_fdbuf(&ssin,read,fdin,inbuf,sizeof(inbuf));
  if (getln(&ssin,&line,&match,'\n') == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_READ,TXT_EZCRONRC));

  if (!match)
    strerr_die2sys(111,FATAL,MSG1(ERR_READ,TXT_EZCRONRC));
	/* (since we have match line.len has to be >= 1) */
  line.s[line.len - 1] = '\0';
  if (!isclean(line.s,0))	 /* host for bounces */
    strerr_die2x(100,FATAL,MSG1(ERR_CFHOST,TXT_EZCRONRC));
  if (!stralloc_copys(&rp,line.s)) die_nomem();

  match = 1;
  for(;;) {
    if (!match) break;		/* to allow last line without '\n' */
    if (getln(&ssin,&line,&match,'\n') == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_READ,TXT_EZCRONRC));
    if (!line.len)
      break;
    line.s[line.len-1] = '\0';
    if (!case_startb(line.s,line.len,user.s))
      continue;
    pos = user.len - 1;
    if (pos >= line.len || line.s[pos] != ':')
      continue;
    founduser = 1;		 /* got user line */
    break;
  }
  close(fdin);
  if (!founduser)
    strerr_die2x(100,FATAL,MSG(ERR_BADUSER));
  
  if (flagconfig) {
    line.s[line.len-1] = '\n';	/* not very elegant ;-) */
    substdio_fdbuf(&ssout,write,1,outbuf,sizeof(outbuf));
    if (substdio_put(&ssout,line.s,line.len) == -1)
      strerr_die2sys(111,FATAL,MSG(ERR_WRITE_STDOUT));
    if (substdio_flush(&ssout) == -1)
      strerr_die2sys(111,FATAL,MSG(ERR_WRITE_STDOUT));
    _exit(0);
  }
  ++pos;				/* points to first ':' */
  len = str_chr(line.s+pos,':');	/* second ':' */
    if (!line.s[pos + len])
      die_syntax(&line);
  if (!local) {				/* only -d and std left */
    localmatch = 1;
    hostmatch = 1;
  } else {
    hostmatch = 0;
    if (len <= str_len(local))
      if (!str_diffn(line.s+pos,local,len))
        localmatch = 1;
  }
  pos += len + 1;
  len = str_chr(line.s + pos,':');	/* third */
  if (!line.s[pos + len])
    die_syntax(&line);
  if (local) {				/* check host */
    if (len == 0)			/* empty host => any host */
      hostmatch = 1;
    else
      if (len == str_len(host))
        if (!case_diffb(line.s+pos,len,host))
          hostmatch = 1;
  }
  pos += len + 1;
  pos += scan_ulong(line.s+pos,&maxlists);
  if (line.s[pos]) {			/* check additional lists */
    if (line.s[pos] != ':')
      die_syntax(&line);
    if (line.s[pos+1+str_chr(line.s+pos+1,':')])
      die_syntax(&line);	/* reminder lists are not separated by ':'  */
				/* otherwise a ':' or arg miscount will die */
				/* silently */
    if (local) {
      while (++pos < line.len) {
        len = str_chr(line.s + pos,'@');
        if (len == lenlocal && !str_diffn(line.s + pos,local,len)) {
          pos += len;
          if (!line.s[pos]) break;
          pos++;
          len = str_chr(line.s+pos,',');
            if (len == lenhost && !case_diffb(line.s+pos,len,host)) {
              listmatch = 1;
              break;
            }
        }
        pos += len;
      }
    }
  }
  if (!listmatch) {
    if (!hostmatch)
      strerr_die2x(100,FATAL,MSG(ERR_BADHOST));
    if (!localmatch)
      strerr_die2x(100,FATAL,MSG(ERR_BADLOCAL));
  }
	/* assemble correct line */
  if (!flaglist) {
    if (!stralloc_copyb(&addr,strnum,fmt_ulong(strnum,mm))) die_nomem();
    if (!stralloc_cats(&addr," ")) die_nomem();
    dh = 0L;
    if (deltah <= 3L) dh = deltah;
    else if (deltah <= 6L) dh = 6L;
    else if (deltah <= 12L) dh = 12L;
    else if (deltah <= 24L) dh = 24L;
    else if (deltah <= 48L) {
      if (dow[0] == '*') dow = "1,3,5";
    } else if (deltah <= 72L) {
      if (dow[0] == '*') dow = "1,4";
    } else
    if (dow[0] == '*') dow = "1";

    if (!dh) {
      if (!stralloc_cats(&addr,"*")) die_nomem();
    } else {
      if (!stralloc_catb(&addr,strnum,fmt_ulong(strnum,hh))) die_nomem();
      for (t = hh + dh; t < hh + 24L; t+=dh) {
        if (!stralloc_cats(&addr,",")) die_nomem();
        if (!stralloc_catb(&addr,strnum,fmt_ulong(strnum,t % 24L))) die_nomem();
      }
    }
    if (!stralloc_cats(&addr," * * ")) die_nomem();
    if (!stralloc_cats(&addr,dow)) die_nomem();
    if (!stralloc_cats(&addr," ")) die_nomem();
    if (!stralloc_cats(&addr,auto_qmail)) die_nomem();
    if (!stralloc_cats(&addr,qmail_inject)) die_nomem();
    if (!stralloc_cats(&addr,local)) die_nomem();
    if (!stralloc_cats(&addr,"-dig-")) die_nomem();
    if (!stralloc_cats(&addr,code)) die_nomem();
    if (!stralloc_cats(&addr,"@")) die_nomem();
    if (!stralloc_cats(&addr,host)) die_nomem();
		/* feed 'Return-Path: <user@host>' to qmail-inject */
    if (!stralloc_cats(&addr,"%Return-path: <")) die_nomem();
    if (!stralloc_cats(&addr,user.s)) die_nomem();
    if (!stralloc_cats(&addr,"@")) die_nomem();
    if (!stralloc_cat(&addr,&rp)) die_nomem();
    if (!stralloc_cats(&addr,">\n")) die_nomem();
  }
  if (!stralloc_0(&addr)) die_nomem();

  if (!flaglist) {
	/* now to rewrite crontab we need to lock */
    lockfile("crontabl");
  } /* if !flaglist */
  if ((fdin = open_read("crontab")) == -1) {
    if (errno != error_noent)
      strerr_die2sys(111,FATAL,MSG1(ERR_READ,"crontab"));
  } else
    substdio_fdbuf(&ssin,read,fdin,inbuf,sizeof(inbuf));
  if (flaglist)
    substdio_fdbuf(&ssout,write,1,outbuf,sizeof(outbuf));
  else {
    if ((fdout = open_trunc("crontabn")) == -1)
      strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,"crontabn"));
    substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof(outbuf));
  }
  line.len = 0;

  if (fdin != -1) {
    for (;;) {
      if (!flaglist && line.len) {
        line.s[line.len-1] = '\n';
        if (substdio_put(&ssout,line.s,line.len) == -1)
          strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,"crontabn"));
      }
      if (getln(&ssin,&line,&match,'\n') == -1)
        strerr_die2sys(111,FATAL,MSG1(ERR_READ,"crontab"));
      if (!match)
        break;
      flagours = 0;			/* assume entry is not ours */
      foundlocal = 0;
      line.s[line.len - 1] = '\0';	/* match so at least 1 char */
      pos = 0;
      while (line.s[pos] == ' ' || line.s[pos] == '\t') ++pos;
      if (line.s[pos] == '#')
        continue;			/* cron comment */
      pos = str_chr(line.s,'/');
      if (!str_start(line.s+pos,auto_qmail)) continue;
      pos += str_len(auto_qmail);
      if (!str_start(line.s+pos,qmail_inject)) continue;
      pos += str_len(qmail_inject);
      poslocal = pos;
      pos = byte_rchr(line.s,line.len,'<');	/* should be Return-Path: < */
      if (pos == line.len)
        continue;			/* not ezmlm-cron line */
      pos++;
     len = str_chr(line.s+pos,'@');
      if (len == user.len - 1 && !str_diffn(line.s+pos,user.s,len)) {
        flagours = 1;
        ++nolists;		/* belongs to this user */
      }
      if (!local) {
        foundlocal = 1;
      } else {
        pos = poslocal + str_chr(line.s+poslocal,'@');
        if (pos + lenhost +1 >= line.len) continue;
        if (case_diffb(line.s+pos+1,lenhost,host)) continue;
        if (line.s[pos+lenhost+1] != '%') continue;
				/* check local */
        if (poslocal + lenlocal + 5 >= line.len) continue;
        if (!str_start(line.s+poslocal,local)) continue;
        pos2 = poslocal+lenlocal;
        if (!str_start(line.s+pos2,"-dig-")) continue;
        foundlocal = 1;
      }
      if (foundlocal) {
        foundmatch = 1;
        if (flaglist && (local || flagours)) {
          if (substdio_put(&ssout,line.s,line.len) == -1)
            strerr_die2sys(111,FATAL,MSG(ERR_WRITE_STDOUT));
          if (substdio_put(&ssout,"\n",1) == -1)
            strerr_die2sys(111,FATAL,MSG(ERR_WRITE_STDOUT));
        }
        line.len = 0;		/* same - kill line */
        if (flagours)
          --nolists;
      }
    }
    close(fdin);
  }
  if (flaglist) {
    if (substdio_flush(&ssout) == -1)
      strerr_die2sys(111,FATAL,MSG1(ERR_FLUSH,"stdout"));
    if (foundmatch)		/* means we had a match */
      _exit(0);
    else
      strerr_die2x(100,FATAL,MSG(ERR_NO_MATCH));
  }
	/* only -d and regular use left */

  if (nolists >= maxlists && !flagdelete)
    strerr_die2x(100,FATAL,MSG(ERR_LISTNO));
  if (!flagdelete)
    if (substdio_put(&ssout,addr.s,addr.len-1) == -1)
      strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,"crontabn"));
  if (flagdelete && !foundlocal)
    strerr_die2x(111,FATAL,MSG(ERR_NO_MATCH));
  if (substdio_flush(&ssout) == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_FLUSH,"crontabn"));
  if (fsync(fdout) == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_SYNC,"crontabn++"));
  if (close(fdout) == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_CLOSE,"crontabn"));
  wrap_rename("crontabn","crontab");
  sendargs[0] = "sh";
  sendargs[1] = "-c";

  if (!stralloc_copys(&line,auto_cron)) die_nomem();
  if (!stralloc_cats(&line,"/crontab '")) die_nomem();
  if (!stralloc_cats(&line,dir.s)) die_nomem();
  if (!stralloc_cats(&line,"/crontab'")) die_nomem();
  if (!stralloc_0(&line)) die_nomem();
  sendargs[2] = line.s;
  sendargs[3] = 0;
  if ((child = wrap_fork()) == 0) {
    if (setreuid(euid,euid) == -1)
      strerr_die2sys(100,FATAL,MSG(ERR_SETUID));
    wrap_execvp(sendargs);
  }
  /* parent */
  switch (wrap_waitpid(child)) {
      case 0:
        _exit(0);
      default:
        strerr_die2x(111,FATAL,MSG(ERR_CRONTAB));
  }
}
Beispiel #11
0
/* Add (flagadd=1) or remove (flagadd=0) userhost from the subscriber
 * database table. Comment is e.g. the subscriber from line or name. It
 * is added to the log. Event is the action type, e.g. "probe",
 * "manual", etc. The direction (sub/unsub) is inferred from
 * flagadd. Returns 1 on success, 0 on failure. If forcehash is >=0 it
 * is used in place of the calculated hash. This makes it possible to
 * add addresses with a hash that does not exist. forcehash has to be
 * 0..99.  For unsubscribes, the address is only removed if forcehash
 * matches the actual hash. This way, ezmlm-manage can be prevented from
 * touching certain addresses that can only be removed by
 * ezmlm-unsub. Usually, this would be used for sublist addresses (to
 * avoid removal) and sublist aliases (to prevent users from subscribing
 * them (although the cookie mechanism would prevent the resulting
 * duplicate message from being distributed. */
int sub_sql_subscribe(struct subdbinfo *info,
		      const char *table,
		      const char *userhost,
		      int flagadd,
		      const char *comment,
		      const char *event,
		      int forcehash)
{
  void *result;
  char *cpat;
  char szhash[3] = "00";

  unsigned int j;
  unsigned char ch;
  int nparams;

  make_name(info,table?"_":0,table,0);

  /* lowercase and check address */
  stralloc_copys(&addr,userhost);
  if (addr.len > 255)			/* this is 401 in std ezmlm. 255 */
					/* should be plenty! */
    strerr_die2x(100,FATAL,MSG(ERR_ADDR_LONG));
  j = byte_rchr(addr.s,addr.len,'@');
  if (j == addr.len)
    strerr_die2x(100,FATAL,MSG(ERR_ADDR_AT));
  cpat = addr.s + j;
  case_lowerb(cpat + 1,addr.len - j - 1);

  if (forcehash < 0) {
    stralloc_copy(&lcaddr,&addr);
    case_lowerb(lcaddr.s,j);		/* make all-lc version of address */
    ch = subhashsa(&lcaddr);
  } else
    ch = (forcehash % 100);

  szhash[0] = '0' + ch / 10;		/* hash for sublist split */
  szhash[1] = '0' + (ch % 10);

  if (flagadd) {
    /* FIXME: LOCK TABLES name WRITE */
    stralloc_copys(&query,"SELECT address FROM ");
    stralloc_cat(&query,&name);
    stralloc_cats(&query," WHERE ");
    stralloc_cats(&query,sql_subscribe_select_where_defn);
    stralloc_copy(&params[0],&addr);
    result = sql_select(info,&query,1,params);
    if (sql_fetch_row(info,result,1,params)) {
      sql_free_result(info,result);
      /* FIXME: UNLOCK TABLES */
      return 0;			/* already subscribed */
    } else {			/* not there */
      sql_free_result(info,result);

      stralloc_copys(&query,"INSERT INTO ");
      stralloc_cat(&query,&name);
      stralloc_cats(&query," (address,hash) VALUES ");
      stralloc_cats(&query,sql_subscribe_list_values_defn);
      stralloc_copy(&params[0],&addr);
      stralloc_copys(&params[1],szhash);
      sql_exec(info,&query,2,params);
      /* FIXME: UNLOCK TABLES */
    }
  } else {							/* unsub */
    stralloc_copys(&query,"DELETE FROM ");
    stralloc_cat(&query,&name);
    stralloc_cats(&query," WHERE ");
    stralloc_copy(&params[0],&addr);
    if (forcehash >= 0) {
      stralloc_cats(&query,sql_subscribe_delete2_where_defn);
      stralloc_copys(&params[1],szhash);
      nparams = 2;
    }
    else {
      stralloc_cats(&query,sql_subscribe_delete1_where_defn);
      nparams = 1;
    }
    if (sql_exec(info,&query,1,params) == 0)
      return 0;			/* address wasn't there*/
  }

  /* log to subscriber log */
  /* INSERT INTO t_slog (address,edir,etype,fromline) */
  /* VALUES('address',{'+'|'-'},'etype','[comment]') */

  stralloc_copys(&query,"INSERT INTO ");
  stralloc_cat(&query,&name);
  stralloc_cats(&query,"_slog (address,edir,etype,fromline) VALUES ");
  stralloc_cats(&query,sql_subscribe_slog_values_defn);
  stralloc_copy(&params[0],&addr);
  stralloc_copys(&params[1],flagadd?"+":"-"); /* edir */
  stralloc_copyb(&params[2],event+1,!!*(event+1)); /* etype */
  stralloc_copys(&params[3],comment && *comment ? comment : ""); /* from */

  sql_exec(info,&query,4,params); /* log (ignore errors) */
  stralloc_0(&addr);
  logaddr(table,event,addr.s,comment);   /* also log to old log */
  return 1;				 /* desired effect */
}
Beispiel #12
0
const char *issub(const char *dir,
		  const char *subdir,
		  const char *userhost)
/* Returns (char *) to match if userhost is in the subscriber database      */
/* dir, 0 otherwise. dir is a base directory for a list and may NOT         */
/* be NULL        */
/* NOTE: The returned pointer is NOT VALID after a subsequent call to issub!*/

{
  MYSQL_RES *result;
  MYSQL_ROW row;
  const char *ret;
  const char *table;
  unsigned long *lengths;

  unsigned int j;

  if ((ret = opensub(dir,subdir,&table))) {
    if (*ret) strerr_die2x(111,FATAL,ret);

    return std_issub(dir,subdir,userhost);

  } else {						/* SQL version  */
	/* SELECT address FROM list WHERE address = 'userhost' AND hash */
	/* BETWEEN 0 AND 52. Without the hash restriction, we'd make it */
	/* even easier to defeat. Just faking sender to the list name would*/
	/* work. Since sender checks for posts are bogus anyway, I don't */
	/* know if it's worth the cost of the "WHERE ...". */

    if (!stralloc_copys(&addr,userhost)) die_nomem();
    j = byte_rchr(addr.s,addr.len,'@');
    if (j == addr.len) return 0;
    case_lowerb(addr.s + j + 1,addr.len - j - 1);

    if (!stralloc_copys(&line,"SELECT address FROM ")) die_nomem();
    if (!stralloc_cats(&line,table)) die_nomem();
    if (!stralloc_cats(&line," WHERE address = '")) die_nomem();
    if (!stralloc_ready(&quoted,2 * addr.len + 1)) die_nomem();
    if (!stralloc_catb(&line,quoted.s,
	mysql_escape_string(quoted.s,userhost,addr.len))) die_nomem();
    if (!stralloc_cats(&line,"'"))
		die_nomem();
    if (mysql_real_query(mysql,line.s,line.len))	/* query */
		strerr_die2x(111,FATAL,mysql_error(mysql));
    if (!(result = mysql_use_result(mysql)))
		strerr_die2x(111,FATAL,mysql_error(mysql));
    row = mysql_fetch_row(result);
    ret = (char *) 0;
    if (!row) {		/* we need to return the actual address as other */
			/* dbs may accept user-*@host, but we still want */
			/* to make sure to send to e.g the correct moderator*/
			/* address. */
      if (!mysql_eof(result))
		strerr_die2x(111,FATAL,mysql_error(mysql));
    } else {
      if (!(lengths = mysql_fetch_lengths(result)))
		strerr_die2x(111,FATAL,mysql_error(mysql));
      if (!stralloc_copyb(&line,row[0],lengths[0])) die_nomem();
      if (!stralloc_0(&line)) die_nomem();
      ret = line.s;
      while ((row = mysql_fetch_row(result)));	/* maybe not necessary */
      mysql_free_result(result);
    }
    return ret;
  }
}
Beispiel #13
0
int main(int argc,char **argv)
{
  char strnum[FMT_ULONG];
  char *action;
  char *dtline;
  char *nhost;
  const char *err;
  unsigned int i;
  int match;
  int opt;

  sig_pipeignore();

  opt = getconfopt(argc,argv,options,1,0);
  if (!(split = argv[opt]))
    split = "split";

  if (flagdo) {
    sender = get_sender();
    if (!sender) die_sender();
    if (!*sender)
      strerr_die2x(100,FATAL,MSG(ERR_BOUNCE));
    if (!sender[str_chr(sender,'@')])
      strerr_die2x(100,FATAL,MSG(ERR_ANONYMOUS));
    if (str_equal(sender,"#@[]"))
      strerr_die2x(100,FATAL,MSG(ERR_BOUNCE));

    action = env_get("DEFAULT");
    if (!action) strerr_die2x(100,FATAL,MSG(ERR_NODEFAULT));
    if (!stralloc_copys(&target,sender)) die_nomem();
    if (action[0]) {
      i = str_chr(action,'-');
      if (action[i]) {
        action[i] = '\0';
        if (!stralloc_copys(&target,action + i + 1)) die_nomem();
        i = byte_rchr(target.s,target.len,'=');
        if (i < target.len)
	  target.s[i] = '@';
      }
    }
    if (!stralloc_0(&target)) die_nomem();

    if (case_diffs(action,ACTION_SUBSCRIBE) &&
      case_diffs(action,ALT_SUBSCRIBE) &&
      case_diffs(action,ACTION_UNSUBSCRIBE) &&
      case_diffs(action,ALT_UNSUBSCRIBE))
    _exit(0);			/* not for us */

    if (findname()) {
				/* new sender */
      if (!stralloc_copy(&from,&outlocal)) die_nomem();
      if (!stralloc_cats(&from,"-return-@")) die_nomem();
      if (!stralloc_cat(&from,&outhost)) die_nomem();
      if (!stralloc_0(&from)) die_nomem();
      nhost = name.s + str_rchr(name.s,'@');		/* name must have '@'*/
      *(nhost++) = '\0';
      if (!stralloc_copys(&to,name.s)) die_nomem();	/* local */
      if (!stralloc_append(&to,'-')) die_nomem();	/* - */
      if (!stralloc_cats(&to,action)) die_nomem();	/* subscribe */
      if (!stralloc_append(&to,'-')) die_nomem();	/* - */
      if (target.s[i = str_rchr(target.s,'@')])
	target.s[i] = '=';
      if (!stralloc_cats(&to,target.s)) die_nomem();	/* target */
      if (!stralloc_append(&to,'@')) die_nomem();	/* - */
      if (!stralloc_cats(&to,nhost)) die_nomem();	/* host */
      if (!stralloc_0(&to)) die_nomem();
      dtline = env_get("DTLINE");
      if (!dtline) strerr_die2x(100,FATAL,MSG(ERR_NODTLINE));

      if (qmail_open(&qq) == -1)
        strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE));
      qmail_puts(&qq,dtline);				/* delivered-to */
      if (qmail_copy(&qq,subfdin,0) != 0)
        strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
      qmail_from(&qq,from.s);
      qmail_to(&qq,to.s);

      if (*(err = qmail_close(&qq)) != '\0')
        strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1);

      strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0;
      strerr_die3x(99,INFO,"qp ",strnum);
    }
    _exit(0);
  } else {

    for (;;) {
      if (getln(subfdin,&line,&match,'\n') == -1)
	  strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
      if (!match) break;
      if (line.len == 1) continue;	/* ignore blank lines */
      if (line.s[0] == '#') continue;	/* ignore comments */
      if (!stralloc_copy(&target,&line)) die_nomem();
      target.s[target.len - 1] = '\0';
      (void) findname();
      if (!stralloc_cats(&name,": ")) die_nomem();
      if (!stralloc_cats(&name,target.s)) die_nomem();
      if (!stralloc_append(&name,'\n')) die_nomem();
      if (substdio_put(subfdout,name.s,name.len) == -1)
	strerr_die2sys(111,FATAL,MSG(ERR_WRITE_STDOUT));
    }
    if (substdio_flush(subfdout) == -1)
      strerr_die2sys(111,FATAL,MSG(ERR_FLUSH_STDOUT));
    _exit(0);
  }
  (void)argc;
}
Beispiel #14
0
/* Add (flagadd=1) or remove (flagadd=0) userhost from the subscriber
 * database table. Comment is e.g. the subscriber from line or name. It
 * is added to the log. Event is the action type, e.g. "probe",
 * "manual", etc. The direction (sub/unsub) is inferred from
 * flagadd. Returns 1 on success, 0 on failure. If forcehash is >=0 it
 * is used in place of the calculated hash. This makes it possible to
 * add addresses with a hash that does not exist. forcehash has to be
 * 0..99.  For unsubscribes, the address is only removed if forcehash
 * matches the actual hash. This way, ezmlm-manage can be prevented from
 * touching certain addresses that can only be removed by
 * ezmlm-unsub. Usually, this would be used for sublist addresses (to
 * avoid removal) and sublist aliases (to prevent users from subscribing
 * them (although the cookie mechanism would prevent the resulting
 * duplicate message from being distributed. */
static int _subscribe(struct subdbinfo *info,
                      const char *table,
                      const char *userhost,
                      int flagadd,
                      const char *comment,
                      const char *event,
                      int forcehash)
{
    sqlite3_stmt *stmt;
    char *cpat;
    char szhash[3] = "00";
    int res;

    unsigned int j;
    unsigned char ch;

    domain.len = 0;			/* clear domain */
    /* lowercase and check address */
    if (!stralloc_copys(&addr,userhost)) die_nomem();
    if (addr.len > 255)			/* this is 401 in std ezmlm. 255 */
        /* should be plenty! */
        strerr_die2x(100,FATAL,MSG(ERR_ADDR_LONG));
    j = byte_rchr(addr.s,addr.len,'@');
    if (j == addr.len)
        strerr_die2x(100,FATAL,MSG(ERR_ADDR_AT));
    cpat = addr.s + j;
    case_lowerb(cpat + 1,addr.len - j - 1);
    if (!stralloc_copy(&quoted, &addr)) die_nomem();
    /* stored unescaped, so it should be ok if quoted.len is >255, as */
    /* long as addr.len is not */

    if (forcehash < 0) {
        if (!stralloc_copy(&lcaddr,&addr)) die_nomem();
        case_lowerb(lcaddr.s,j);		/* make all-lc version of address */
        ch = subhashsa(&lcaddr);
    } else
        ch = (forcehash % 100);

    szhash[0] = '0' + ch / 10;		/* hash for sublist split */
    szhash[1] = '0' + (ch % 10);

    if (flagadd) {
        if (!stralloc_copys(&line,"SELECT address FROM ")) die_nomem();
        if (!stralloc_cat_table(&line,info,table)) die_nomem();
        if (!stralloc_cats(&line," WHERE address LIKE '")) die_nomem();
        if (!stralloc_cat(&line,&quoted)) die_nomem();	/* addr */
        if (!stralloc_cats(&line,"'")) die_nomem();
        if (!stralloc_0(&line)) die_nomem();

        if ((stmt = _sqlquery(info, &line)) == NULL)
            strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn));

        res = sqlite3_step(stmt);
        sqlite3_finalize(stmt);

        if (res == SQLITE_ROW)
            return 0;						/* there */
        else if (res != SQLITE_DONE)
        {
            strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn));
        } else {							/* not there */
            if (!stralloc_copys(&line,"INSERT INTO ")) die_nomem();
            if (!stralloc_cat_table(&line,info,table)) die_nomem();
            if (!stralloc_cats(&line," (address,hash) VALUES ('"))
                die_nomem();
            if (!stralloc_cat(&line,&quoted)) die_nomem();	/* addr */
            if (!stralloc_cats(&line,"',")) die_nomem();
            if (!stralloc_cats(&line,szhash)) die_nomem();	/* hash */
            if (!stralloc_cats(&line,")")) die_nomem();
            if (!stralloc_0(&line)) die_nomem();

            if ((stmt = _sqlquery(info, &line)) == NULL)
                strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn));

            if (sqlite3_step(stmt) != SQLITE_DONE)
                strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn));

            sqlite3_finalize(stmt);
        }
    } else {							/* unsub */
        if (!stralloc_copys(&line,"DELETE FROM ")) die_nomem();
        if (!stralloc_cat_table(&line,info,table)) die_nomem();
        if (!stralloc_cats(&line," WHERE address LIKE '")) die_nomem();
        if (!stralloc_cat(&line,&quoted)) die_nomem();	/* addr */
        if (forcehash >= 0) {
            if (!stralloc_cats(&line,"' AND hash=")) die_nomem();
            if (!stralloc_cats(&line,szhash)) die_nomem();
        } else {
            if (!stralloc_cats(&line,"' AND hash BETWEEN 0 AND 52"))
                die_nomem();
        }

        if (!stralloc_0(&line)) die_nomem();

        if ((stmt = _sqlquery(info, &line)) == NULL)
            strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn));

        if (sqlite3_step(stmt) != SQLITE_DONE)
            strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn));

        sqlite3_finalize(stmt);

        if (sqlite3_changes((sqlite3*)info->conn) == 0)
            return 0;				/* address wasn't there*/
    }

    /* log to subscriber log */
    /* INSERT INTO t_slog (address,edir,etype,fromline) */
    /* VALUES('address',{'+'|'-'},'etype','[comment]') */

    if (!stralloc_copys(&logline,"INSERT INTO ")) die_nomem();
    if (!stralloc_cat_table(&logline,info,table)) die_nomem();
    if (!stralloc_cats(&logline,
                       "_slog (tai,address,edir,etype,fromline) VALUES ("))
        die_nomem();
    if (!stralloc_catb(&logline,strnum,fmt_ulong(strnum,now()))) die_nomem();
    if (!stralloc_cats(&logline,",'")) die_nomem();
    if (!stralloc_cat(&logline,&quoted)) die_nomem();
    if (flagadd) {						/* edir */
        if (!stralloc_cats(&logline,"','+','")) die_nomem();
    } else {
        if (!stralloc_cats(&logline,"','-','")) die_nomem();
    }
    if (*(event + 1))	/* ezmlm-0.53 uses '' for ezmlm-manage's work */
        if (!stralloc_catb(&logline,event+1,1)) die_nomem();	/* etype */
    if (!stralloc_cats(&logline,"','")) die_nomem();
    if (comment && *comment) {
        j = str_len(comment);
        if (!stralloc_copys(&quoted, comment)) die_nomem();	/* from */
        if (!stralloc_cat(&logline,&quoted)) die_nomem();
    }
    if (!stralloc_cats(&logline,"')")) die_nomem();
    if (!stralloc_0(&logline)) die_nomem();

    if ((stmt = _sqlquery(info, &logline)) != NULL)
    {
        sqlite3_step(stmt);			/* log (ignore errors) */
        sqlite3_finalize(stmt);
    }

    if (!stralloc_0(&addr))
        ;				/* ignore errors */
    logaddr(table,event,addr.s,comment);	/* also log to old log */
    return 1;					/* desired effect */
}
Beispiel #15
0
int main() {
  memset(buf,0,sizeof(buf));
  strcpy(text,"this is a test!\n");

//  carp("both aligned");
  byte_copy(buf,16,text);
  assert(memcmp(buf,"this is a test!\n\0",18)==0);

  memset(buf,0,sizeof(buf));
//  carp("destination aligned, source unaligned");
  byte_copy(buf,15,text+1);
  assert(memcmp(buf,"his is a test!\n\0\0",18)==0);

  memset(buf,0,sizeof(buf));
//  carp("destination unaligned, source aligned");
  byte_copy(buf+1,15,text);
  assert(memcmp(buf,"\0this is a test!\0\0",18)==0);

  memset(buf,0,sizeof(buf));
//  carp("both unaligned");
  byte_copy(buf+1,10,text+3);
  assert(memcmp(buf,"\0s is a tes\0\0",14)==0);

  memset(buf,0,sizeof(buf));
  byte_copyr(buf,16,text);
  assert(memcmp(buf,"this is a test!\n\0",18)==0);

  memset(buf,0,sizeof(buf));
  byte_copyr(buf,15,text+1);
  assert(memcmp(buf,"his is a test!\n\0\0",18)==0);

  memset(buf,0,sizeof(buf));
  byte_copyr(buf+1,15,text);
  assert(memcmp(buf,"\0this is a test!\0\0",18)==0);

  memset(buf,0,sizeof(buf));
  byte_copyr(buf+1,10,text+3);
  assert(memcmp(buf,"\0s is a tes\0\0",14)==0);

  memset(buf,0,sizeof(buf));
  byte_copy(buf,16,text);
  byte_copy(buf,16,buf+1);
  assert(memcmp(buf,"his is a test!\n\0\0",18)==0);

  memset(buf,0,sizeof(buf));
  byte_copy(buf,16,text);
  byte_copyr(buf+1,16,buf);
  assert(memcmp(buf,"tthis is a test!\n",18)==0);

  assert(byte_diff(text,15,"this is a test!")==0);
  assert(byte_diff(text,16,"this is a test!")>0);
  assert(byte_diff("this is a test!",16,text)<0);

  assert(byte_chr("0123456789abcdef",17,'9')==9);
  assert(byte_rchr("0123456789abcdef",17,'9')==9);
  assert(byte_chr("0123456789abcdef",17,'A')==17);
  assert(byte_rchr("0123456789abcdef",17,'A')==17);

  byte_zero(buf,16);
  assert(byte_equal(buf,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"));

  return 0;
}
Beispiel #16
0
int findname(void)
/* returns 1 if a matching line was found, 0 otherwise. name will contain */
/* the correct list address in either case */
{
  char *cpat,*cp1,*cp2,*cplast;
  const char *cpname;
  unsigned long u;
  unsigned char hash,hash_hi,hash_lo;
  unsigned int pos,pos_name,pos_hi;
  int fd,match;

  /* make case insensitive hash */
  flagfound = 0;			/* default */
  cpname = "";				/* default */
  if (!stralloc_copy(&lctarget,&target)) die_nomem();
  case_lowerb(lctarget.s,lctarget.len -1);
  hash = subhashs(lctarget.s);

  /* make domain pointer */
  cpat = lctarget.s + str_chr(lctarget.s,'@');
  if (!*cpat)
    strerr_die4x(100,FATAL,ERR_ADDR_AT,": ",target.s);
  cplast = cpat + str_len(cpat) - 1;
  if (*cplast == '.') --cplast;		/* annonying special case */
  cp1 = cpat + byte_rchr(cpat,cplast - cpat, '.');
  if (cp1 != cplast) {			/* got one '.' */
    if (!stralloc_copyb(&domain,cp1 + 1, cplast - cp1)) die_nomem();
    cp2 = cpat + byte_rchr(cpat, cp1 - cpat,'.');
    if (cp2 == cp1) cp2 = cpat;
    ++cp2;
    if (!stralloc_append(&domain,".")) die_nomem();
    if (!stralloc_catb(&domain,cp2, cp1 - cp2)) die_nomem();
  } else				/* no '.' */
    if (!stralloc_copyb(&domain,cpat + 1,cplast - cpat)) die_nomem();
  if (!stralloc_0(&domain)) die_nomem();

  if ((fd = open_read(split)) == -1)
    strerr_die4sys(111,FATAL,ERR_OPEN,split,": ");
  substdio_fdbuf(&sssp,read,fd,spbuf,(int) sizeof(spbuf));
  lineno = 0;
  for (;;) {	/* dom:hash_lo:hash_hi:listaddress */
    if (getln(&sssp,&line,&match,'\n') == -1)
      strerr_die4sys(111,FATAL,ERR_READ,split,": ");
     lineno++;
    if (!match)
      break;
    if (line.s[0] == '#') continue;	/* comment */
    line.s[line.len - 1] = '\0';	/* no need to allow \0 in lines */
    if (!line.s[pos = str_chr(line.s,':')])
      continue;				/* usually blank line */
    line.s[pos] = '\0';
    if (pos == 0 ||			/* no domain */
	  (case_starts(domain.s,line.s))) {	/* or matching domain */
	if (!line.s[++pos]) die_syntax();
	pos_hi = pos + str_chr(line.s + pos,':');
	if (!line.s[pos_hi]) die_syntax();
	pos_hi++;
	(void) scan_ulong(line.s + pos, &u);	/* scan_uint() not in ezmlm */
	hash_lo = (unsigned char) u;
	(void) scan_ulong(line.s + pos_hi, &u);
	hash_hi = (unsigned char) u;
	pos_name = pos_hi + str_chr(line.s + pos_hi,':');
	if (pos_hi == pos_name) hash_hi = 52L;	/* default hi = 52 */
	if (line.s[pos_name]) pos_name++;
	if (hash > hash_hi || hash < hash_lo) continue;	/* not us */
	cpname = line.s + pos_name;
	while (*cpname &&				/* isolate name */
	    (*cpname == ' ' || *cpname == '\t')) cpname++;
	pos = line.len - 2;
	while (pos && (line.s[pos] == '\n' || line.s[pos] == ' ' ||
		line.s[pos] == '\t')) line.s[pos--] = '\0';
	break;
    }
  }
  close(fd);

  if (*cpname) {
    if (!stralloc_copys(&name,cpname)) die_nomem();
    if (byte_chr(name.s,name.len,'@') == name.len) {	/* local sublist */
      if (!stralloc_append(&name,"@")) die_nomem();
      if (!stralloc_cat(&name,&outhost)) die_nomem();
    }
    if (!stralloc_0(&name)) die_nomem();
    return 1;
  } else {			/* match without name or no match =>this list */
    if (!stralloc_copy(&name,&outlocal)) die_nomem();
    if (!stralloc_append(&name,"@")) die_nomem();
    if (!stralloc_cat(&name,&outhost)) die_nomem();
    if (!stralloc_0(&name)) die_nomem();
    return 0;
  }
}
Beispiel #17
0
void main(int argc,char **argv)
{
  char *dir;
  char *action;
  char *dtline;
  char *nhost;
  const char *err;
  unsigned int i;
  int match;
  int opt;

  sig_pipeignore();

  while ((opt = getopt(argc,argv,"dDvV")) != opteof) {
    switch (opt) {
    case 'd': flagdo = 1; break;
    case 'D': flagdo = 0; break;
    case 'v':
    case 'V':
      strerr_die2x(0, "ezmlm-split version: ",auto_version);
    default:
      die_usage();
    }
  }

  startup(dir = argv[optind++]);
  load_config(dir);
  if (!(split = argv[optind]))
    split = "split";

  if (flagdo) {
    sender = env_get("SENDER");
    if (!sender) strerr_die2x(100,FATAL,ERR_NOSENDER);
    if (!*sender)
      strerr_die2x(100,FATAL,ERR_BOUNCE);
    if (!sender[str_chr(sender,'@')])
      strerr_die2x(100,FATAL,ERR_ANONYMOUS);
    if (str_equal(sender,"#@[]"))
      strerr_die2x(100,FATAL,ERR_BOUNCE);

    action = env_get("DEFAULT");
    if (!action) strerr_die2x(100,FATAL,ERR_NODEFAULT);
    if (!stralloc_copys(&target,sender)) die_nomem();
    if (action[0]) {
      i = str_chr(action,'-');
      if (action[i]) {
        action[i] = '\0';
        if (!stralloc_copys(&target,action + i + 1)) die_nomem();
        i = byte_rchr(target.s,target.len,'=');
        if (i < target.len)
	  target.s[i] = '@';
      }
    }
    if (!stralloc_0(&target)) die_nomem();

    if (case_diffs(action,ACTION_SUBSCRIBE) &&
      case_diffs(action,ALT_SUBSCRIBE) &&
      case_diffs(action,ACTION_UNSUBSCRIBE) &&
      case_diffs(action,ALT_UNSUBSCRIBE))
    _exit(0);			/* not for us */

    if (findname()) {
				/* new sender */
      if (!stralloc_copy(&from,&outlocal)) die_nomem();
      if (!stralloc_cats(&from,"-return-@")) die_nomem();
      if (!stralloc_cat(&from,&outhost)) die_nomem();
      if (!stralloc_0(&from)) die_nomem();
      nhost = name.s + str_rchr(name.s,'@');		/* name must have '@'*/
      *(nhost++) = '\0';
      if (!stralloc_copys(&to,name.s)) die_nomem();	/* local */
      if (!stralloc_append(&to,"-")) die_nomem();	/* - */
      if (!stralloc_cats(&to,action)) die_nomem();	/* subscribe */
      if (!stralloc_append(&to,"-")) die_nomem();	/* - */
      if (target.s[i = str_rchr(target.s,'@')])
	target.s[i] = '=';
      if (!stralloc_cats(&to,target.s)) die_nomem();	/* target */
      if (!stralloc_append(&to,"@")) die_nomem();	/* - */
      if (!stralloc_cats(&to,nhost)) die_nomem();	/* host */
      if (!stralloc_0(&to)) die_nomem();
      dtline = env_get("DTLINE");
      if (!dtline) strerr_die2x(100,FATAL,ERR_NODTLINE);

      if (qmail_open(&qq,(stralloc *) 0) == -1)
        strerr_die2sys(111,FATAL,ERR_QMAIL_QUEUE);
      qmail_puts(&qq,dtline);				/* delivered-to */
      if (qmail_copy(&qq,subfdin,0) != 0)
        strerr_die2sys(111,FATAL,ERR_READ_INPUT);
      qmail_from(&qq,from.s);
      qmail_to(&qq,to.s);

      if (*(err = qmail_close(&qq)) != '\0')
        strerr_die3x(111,FATAL,ERR_TMP_QMAIL_QUEUE,err + 1);

      strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0;
      strerr_die3x(99,INFO,"qp ",strnum);
    }
    _exit(0);
  } else {

    for (;;) {
      if (getln(subfdin,&line,&match,'\n') == -1)
	  strerr_die2sys(111,FATAL,ERR_READ_INPUT);
      if (!match) break;
      if (line.len == 1) continue;	/* ignore blank lines */
      if (line.s[0] == '#') continue;	/* ignore comments */
      if (!stralloc_copy(&target,&line)) die_nomem();
      target.s[target.len - 1] = '\0';
      (void) findname();
      if (!stralloc_cats(&name,": ")) die_nomem();
      if (!stralloc_cats(&name,target.s)) die_nomem();
      if (!stralloc_append(&name,"\n")) die_nomem();
      if (substdio_put(subfdout,name.s,name.len) == -1)
	strerr_die2sys(111,ERR_WRITE,"output: ");
    }
    if (substdio_flush(subfdout) == -1)
      strerr_die2sys(111,ERR_FLUSH,"output: ");
    _exit(0);
  }
  (void)argc;
}
Beispiel #18
0
int ipsvd_check_cdb(stralloc *data, stralloc *match, char *cdb,
                    char *ip, char *name, unsigned long unused) {
  int ok;
  int i;
  int rc;

  if ((fd =open_read(cdb)) == -1) return(IPSVD_ERR);
  cdb_init(&c, fd);
  if (! stralloc_copys(match, ip)) return(-1);
  if (! stralloc_0(match)) return(-1);
  data->len =0;
  /* ip */
  for (;;) {
    ok =ipsvd_check_cdbentry(data, match, ip, &rc);
    if (ok == -1) return(-1);
    if (ok) {
      if (rc == IPSVD_FORWARD) goto forwarded;
      close(fd);
      return(rc);
    }
    if ((i =byte_rchr(match->s, match->len, '.')) == match->len) break;
    match->s[i] =0; match->len =i +1;
  }
  /* host */
  if (name) {
    for (;;) {
      if (! *name || (*name == '.')) break;
      if (! stralloc_copys(match, name)) return(-1);
      if (! stralloc_0(match)) return(-1);
      ok =ipsvd_check_cdbentry(data, match, ip, &rc);
      if (ok == -1) return(-1);
      if (ok) {
        if (rc == IPSVD_FORWARD) goto forwarded;
        close(fd);
        return(rc);
      }
      if ((i =byte_chr(name, str_len(name), '.')) == str_len(name)) break;
      name +=i +1;
    }
  }
  /* default */
  if (! stralloc_copys(match, "0")) return(-1);
  if (! stralloc_0(match)) return(-1);
  ok =ipsvd_check_cdbentry(data, match, ip, &rc);
  if (ok == -1) return(-1);
  if (ok) {
    if (rc == IPSVD_FORWARD) goto forwarded;
    close(fd);
    return(rc);
  }
  if (! stralloc_copys(match, "")) return(-1);
  if (! stralloc_0(match)) return(-1);
  close(fd);
  return(IPSVD_DEFAULT);

 forwarded:
  if (! stralloc_copys(&forwardfn, forward)) return(-1);
  if (! stralloc_0(&forwardfn)) return(-1);
  ok =ipsvd_check_cdbentry(&moredata, &forwardfn, 0, &rc);
  close(fd);
  if (ok == -1) return(-1);
  --match->len;
  if (! stralloc_cats(match, ",")) return(-1);
  if (! stralloc_cats(match, forwardfn.s)) return(-1);
  if (! stralloc_0(match)) return(-1);
  if (ok) {
    if (rc == IPSVD_EXEC)
      data->len =0;
    else
      data->s[data->len -1] =',';
    if (! stralloc_cat(data, &moredata)) return(-1);
    return(rc);
  }
  strerr_warn4(progname, ": warning: ", match->s, ": not found", 0);
  return(IPSVD_DENY);
}
Beispiel #19
0
int ipsvd_check_dir(stralloc *data, stralloc *match, char *dir,
                    char *ip, char *name, unsigned long timeout) {
  struct stat s;
  int i;
  int rc;
  int ok;
  int base;
  time_t now =0;

  if (stat(dir, &s) == -1) return(IPSVD_ERR);
  if (timeout) now =time((time_t*)0);
  if (! stralloc_copys(match, dir)) return(-1);
  if (! stralloc_cats(match, "/")) return(-1);
  base =match->len;
  /* ip */
  if (ip) {
    if (! stralloc_cats(match, ip)) return(-1);
    if (! stralloc_0(match)) return(-1);
    data->len =0;
    for (;;) {
      ok =ipsvd_check_direntry(data, match, ip, now, timeout, &rc);
      if (ok == -1) return(-1);
      if (ok) {
        if (rc == IPSVD_FORWARD) goto forwarded;
        return(rc);
      }
      if ((i =byte_rchr(match->s, match->len, '.')) == match->len) break;
      if (i <= base) break;
      match->s[i] =0; match->len =i +1;
    }
  }
  /* host */
  if (name) {
    for (;;) {
      if (! *name || (*name == '.')) break;
      match->len =base;
      if (! stralloc_cats(match, name)) return(-1);
      if (! stralloc_0(match)) return(-1);

      ok =ipsvd_check_direntry(data, match, ip, now, timeout, &rc);
      if (ok == -1) return(-1);
      if (ok) {
        if (rc == IPSVD_FORWARD) goto forwarded;
        return(rc);
      }
      if ((i =byte_chr(name, str_len(name), '.')) == str_len(name)) break;
      name +=i +1;
    }
  }
  /* default */
  match->len =base;
  if (! stralloc_cats(match, "0")) return(-1);
  if (! stralloc_0(match)) return(-1);

  ok =ipsvd_check_direntry(data, match, ip, now, timeout, &rc);
  if (ok == -1) return(-1);
  if (ok) {
    if (rc == IPSVD_FORWARD) goto forwarded;
    return(rc);
  }
  if (! stralloc_copys(match, "")) return(-1);
  if (! stralloc_0(match)) return(-1);
  return(IPSVD_DEFAULT);

 forwarded:
  if (! stralloc_copyb(&forwardfn, match->s, base)) return(-1);
  if (! stralloc_cats(&forwardfn, forward)) return(-1);
  if (! stralloc_0(&forwardfn)) return(-1);
  ok =ipsvd_check_direntry(&moredata, &forwardfn, 0, now, timeout, &rc);
  if (ok == -1) return(-1);
  --match->len;
  if (! stralloc_cats(match, ",")) return(-1);
  if (! stralloc_cats(match, forwardfn.s +base)) return(-1);
  if (! stralloc_0(match)) return(-1);
  if (ok) {
    if (rc == IPSVD_EXEC)
      data->len =0;
    else
      data->s[data->len -1] =',';
    if (! stralloc_cat(data, &moredata)) return(-1);
    return(rc);
  }
  strerr_warn4(progname, ": warning: ", match->s, ": not found", 0);
  return(IPSVD_DENY);
}
Beispiel #20
0
int main(int argc,char* argv[]) {
  static size_t x;
  x=23;
  atomic_add(&x,3);
  printf("%u\n",x);
  printf("%u\n",atomic_add_return(&x,-3));
  printf("%u\n",compare_and_swap(&x,26,17));
  printf("%u\n",compare_and_swap(&x,23,17));

#if 0
  atomic_add(&x,3); printf("%u\n",x);
  x=23;
  atomic_add(&x,3); assert(x==26);
  atomic_or(&x,1); assert(x==27);
  atomic_and(&x,-2); assert(x==26);
#endif

#if 0
  iarray a;
  char* c;
  iarray_init(&a,sizeof(io_entry));
  printf("15 -> %p\n",c=iarray_allocate(&a,15));
  printf("23 -> %p\n",c=iarray_allocate(&a,23));
  printf("1234567 -> %p\n",c=iarray_allocate(&a,1234567));
  printf("23 -> %p\n",iarray_get(&a,23));
#endif
#if 0
  io_batch* b=iob_new(1234);
  int64 fd=open("t.c",0);
  iob_addbuf(b,"fnord",5);
  iob_addfile_close(b,fd,0,7365);
  iob_write(1,b,writecb);
#endif
#if 0
  char dest[1024];
  unsigned long len;
  scan_urlencoded2("libstdc++.tar.gz",dest,&len);
  buffer_putmflush(buffer_1,dest,"\n");
#endif
#if 0
  static stralloc sa;
  stralloc_copym(&sa,"foo ","bar ","baz.\n");
  write(1,sa.s,sa.len);
#endif
#if 0
  buffer_putmflush(buffer_1,"foo ","bar ","baz.\n");
#endif
#if 0
  char* c="fnord";
  int fd=open_read(c);
  errmsg_iam(argv[0]);
  carp("could not open file `",c,"'");
  diesys(23,"could not open file `",c,"'");
#endif
#if 0
  errmsg_warn("could not open file `",c,"'",0);
  errmsg_warnsys("could not open file `",c,"'",0);
#endif
#if 0
  char buf[100]="/usr/bin/sh";
  int len=str_len(buf);
  assert(byte_rchr(buf,len,'/')==8);
  assert(byte_rchr(buf,len,'@')==len);
  assert(byte_rchr(buf,len,'h')==len-1);
  printf("%d\n",byte_rchr("x",1,'x'));
#endif
#if 0
  char buf[IP6_FMT+100];
  int i;
  char ip[16];
  uint32 scope_id;
  char* s="fec0::1:220:e0ff:fe69:ad92%eth0/64";
  char blubip[16]="\0\0\0\0\0\0\0\0\0\0\xff\xff\x7f\0\0\001";
  i=scan_ip6if(s,ip,&scope_id);
  assert(s[i]=='/');
  buffer_put(buffer_1,buf,fmt_ip6if(buf,ip,scope_id));
  buffer_putnlflush(buffer_1);
  buffer_put(buffer_1,buf,fmt_ip6ifc(buf,blubip,scope_id));
  buffer_putnlflush(buffer_1);
  scan_ip6("2001:7d0:0:f015:0:0:0:1",ip);
  buffer_put(buffer_1,buf,fmt_ip6(buf,ip));
  buffer_putnlflush(buffer_1);
#endif
#if 0
  char buf[100];
  int i;
  printf("%d\n",i=fmt_pad(buf,"fnord",5,7,10));
  buf[i]=0;
  puts(buf);
#endif
#if 0
  char ip[16];
  char buf[32];
  printf("%d (expect 2)\n",scan_ip6("::",ip));
  printf("%d (expect 3)\n",scan_ip6("::1",ip));
  printf("%d (expect 16)\n",scan_ip6("fec0:0:0:ffff::1/0",ip));
  printf("%.*s\n",fmt_ip6(buf,ip),buf);
#endif
#if 0
  static stralloc s,t;
  stralloc_copys(&s,"fnord");
  stralloc_copys(&t,"abc"); printf("%d\n",stralloc_diff(&s,&t));
  stralloc_copys(&t,"fnor"); printf("%d\n",stralloc_diff(&s,&t));
  stralloc_copys(&t,"fnord"); printf("%d\n",stralloc_diff(&s,&t));
  stralloc_copys(&t,"fnordh"); printf("%d\n",stralloc_diff(&s,&t));
  stralloc_copys(&t,"hausen"); printf("%d\n",stralloc_diff(&s,&t));
#endif
#if 0
  static stralloc s;
  stralloc_copys(&s,"fnord");
  printf("%d\n",stralloc_diffs(&s,"abc"));
  printf("%d\n",stralloc_diffs(&s,"fnor"));
  printf("%d\n",stralloc_diffs(&s,"fnord"));
  printf("%d\n",stralloc_diffs(&s,"fnordh"));
  printf("%d\n",stralloc_diffs(&s,"hausen"));
#endif
#if 0
  printf("%d\n",case_starts("fnordhausen","FnOrD"));
  printf("%d\n",case_starts("fnordhausen","blah"));
#endif
#if 0
  char buf[]="FnOrD";
  case_lowers(buf);
  puts(buf);
#endif
#if 0
  char buf[100]="foo bar baz";
  printf("%d (expect 7)\n",byte_rchr(buf,11,' '));
#endif
#if 0
  unsigned long size;
  char* buf=mmap_read(argv[1],&size);
  if (buf) {
    unsigned int x=fmt_yenc(0,buf,size);
    unsigned int y;
    char* tmp=malloc(x+1);
    y=fmt_yenc(tmp,buf,size);
    write(1,tmp,x);
  }
#endif
#if 0
  char buf[100];
  char buf2[100];
  unsigned int len,len2;
  buf[fmt_yenc(buf,"http://localhost/~fefe",22)]=0;
  buffer_puts(buffer_1,buf);
  buffer_putsflush(buffer_1,"\n");
  if ((buf[len2=scan_yenc(buf,buf2,&len)])!='\n') {
    buffer_putsflush(buffer_2,"parse error!\n");
    return 1;
  }
  buffer_put(buffer_1,buf2,len2);
  buffer_putsflush(buffer_1,"\n");
  return 0;
#endif
#if 0
  char buf[100];
  char buf2[100];
  unsigned int len,len2;
  buf[fmt_base64(buf,"foo:bar",7)]=0;
  buffer_puts(buffer_1,buf);
  buffer_putsflush(buffer_1,"\n");
  if ((buf[len2=scan_base64(buf,buf2,&len)])!=0) {
    buffer_putsflush(buffer_2,"parse error!\n");
    return 1;
  }
  buffer_put(buffer_1,buf2,len2);
  buffer_putsflush(buffer_1,"\n");
  return 0;
#endif
#if 0
  unsigned long size;
  char* buf=mmap_read(argv[1],&size);
  if (buf) {
    unsigned int x=fmt_uuencoded(0,buf,size);
    unsigned int y;
    char* tmp=malloc(x+1);
    y=fmt_uuencoded(tmp,buf,size);
    write(1,tmp,x);
  }
#endif
#if 0
  char buf[]="00000000000000000000000000000001";
  char ip[16];
  if (scan_ip6_flat(buf,ip) != str_len(buf))
    buffer_putsflush(buffer_2,"parse error!\n");
#endif
#if 0
  int fd=open_read("t.c");
  buffer b;
  char buf[1024];
  char line[20];
  int i;
  buffer_init(&b,read,fd,buf,1024);
  i=buffer_getline(&b,line,19);
  buffer_puts(buffer_1,"getline returned ");
  buffer_putulong(buffer_1,i);
  buffer_puts(buffer_1,"\n");
  buffer_puts(buffer_1,line);
  buffer_flush(buffer_1);
#endif
#if 0
  buffer_putulong(buffer_1,23);
//  buffer_putspace(buffer_1);
  buffer_putsflush(buffer_1,"\n");
//  buffer_flush(buffer_1);
#endif
#if 0
  long a,b,c;
  char buf[4096];
  char buf2[4096];
  memcpy(buf,buf2,4096);
  byte_copy(buf,4096,buf2);
  rdtscl(a);
  memcpy(buf,buf2,4096);
  rdtscl(b);
  byte_copy(buf,4096,buf2);
  rdtscl(c);
  printf("memcpy: %d - byte_copy: %d\n",b-a,c-b);
#endif
#if 0
  char ip[16];
  int i;
  if ((i=scan_ip6(argv[1],ip))) {
    char buf[128];
    buf[fmt_ip6(buf,ip)]=0;
    puts(buf);
  }
#endif
#if 0
  char buf[100];
  strcpy(buf,"foobarbaz");
  buf[fmt_fill(buf,3,5,100)]=0;
  printf("\"%s\"\n",buf);
#endif
#if 0
  unsigned long len;
  char *c=mmap_read("/etc/passwd",&len);
  printf("got map %p of len %lu\n",c,len);
#endif
#if 0
  char c;
  printf("%d\n",buffer_getc(buffer_0,&c));
  printf("%c\n",c);
#endif
#if 0
  char buf[100]="01234567890123456789012345678901234567890123456789";
  long a,b,c;
#endif
#if 0
  buf[ip4_fmt(buf,ip4loopback)]=0;
  buffer_puts(buffer_1small,buf);
  buffer_flush(buffer_1small);
#endif

#if 0
  buf[0]=0;
  buf[fmt_8long(buf,0)]=0;
  puts(buf);
  rdtscl(a);
  c=str_len(buf);
  rdtscl(b);
  /*byte_zero_djb(buf,j); */
//  printf("\n%lu %d\n",b-a,c);
#endif
#if 0
  buffer_puts(buffer_1small,"hello, world\n");
  buffer_flush(buffer_1small);
#endif
#if 0
  int s=socket_tcp4();
  char ip[4]={127,0,0,1};
  int t=socket_connect4(s,ip,80);
#endif
#if 0
  char buf[100]="foo bar baz fnord   ";
  char buf2[100]="foo braz fnord";
  long a,b,c;
  long i=0,j=0,k=0;
  double d;
  uint32 l,m,n;
  stralloc sa={0};
  stralloc_copys(&sa,"fnord");
  stralloc_catlong0(&sa,-23,5);
  stralloc_append(&sa,"\n");
  printf("%d %d\n",str_equal("fnord","fnord1"),str_equal("fnord1","fnord"));
  write(1,sa.s,sa.len);
  printf("%d %d\n",stralloc_starts(&sa,"fnord"),stralloc_starts(&sa,"fnord\na"));

  l=0xdeadbeef;
  uint32_pack_big((char*)&m,l);
  uint32_unpack_big((char*)&m,&n);
  printf("%x %x %x\n",l,m,n);

  rdtscl(a);
/*  i=scan_double("3.1415",&d); */
  rdtscl(b);
  /*byte_zero_djb(buf,j); */
  rdtscl(c);
  printf("%lu %lu\n",b-a,c-b);
#endif
#if 0
  size_t size;
  char* buf=mmap_read(argv[1],&size);
  if (buf) {
    unsigned int x=fmt_urlencoded2(0,buf,size,"x");
    unsigned int y;
    char* tmp=malloc(x+1);
    y=fmt_urlencoded2(tmp,buf,size,"x");
    write(1,tmp,x);
  }
#endif
#if 0
  printf("%d %d\n",strcmp("foo","bar"),str_diff("foo","bar"));
  printf("%d %d\n",strcmp("foo","üar"),str_diff("foo","üar"));
#endif
#if 0
  {
    int16 a;
    int32 b;
    int64 c;
    assert(imult16(4,10000,&a)==0);
    assert(imult16(-4,10000,&a)==0);
    assert(imult16(5,10,&a)==1 && a==50);
    assert(imult16(-3,10000,&a)==1 && a==-30000);

    assert(imult32(0x40000000,2,&b)==0);
    assert(imult32(0x3fffffff,2,&b)==1 && b==0x7ffffffe);

    assert(imult64(0x4000000000000000ll,2,&c)==0);
    assert(imult64(0x3fffffffffffffffll,2,&c)==1 && c==0x7ffffffffffffffell);
  }
#endif
#if 0
  stralloc a;
  printf("%d\n",stralloc_copym(&a,"fnord",", ","foo"));
#endif

  return 0;
}
Beispiel #21
0
void sendnotice(const char *d)
/* sends file pointed to by d to the address in the return-path of the  */
/* message. */
{
  unsigned int x,y;
  const char *err;

      if (qmail_open(&qq, (stralloc *) 0) == -1)
        strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE));

      fd = open_read(d);
      if (fd == -1)
        strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,d));
      substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf));
      if (getln(&sstext,&line,&match,'\n') == -1) die_read();
      if (!match) die_read();
      if (!case_startb(line.s,line.len,"return-path:")) die_read();
      x = 12 + byte_chr(line.s + 12,line.len-12,'<');
      y = byte_rchr(line.s + x,line.len-x,'>');
      if (x != line.len && x+y != line.len) {
        if (!stralloc_copyb(&to,line.s+x+1, y-1)) die_nomem();
        if (!stralloc_0(&to)) die_nomem();
      } else
        die_read();
      hdr_add2s("Mailing-List: ",MSG(TXT_MAILING_LIST));
      if (listid.len > 0)
	hdr_add2("List-ID: ",listid.s,listid.len);
      hdr_datemsgid(when+msgnum++);
      hdr_from("-help");
      hdr_subject(MSG(SUB_RETURNED_POST));
      hdr_add2s("To: ",to.s);
      if (flagmime) {
	hdr_mime(CTYPE_MULTIPART);
	hdr_boundary(0);
	hdr_ctype(CTYPE_TEXT);
        hdr_transferenc();
      } else
      qmail_puts(&qq,"\n\n");

      copy(&qq,"text/top",flagcd);
      copy(&qq,"text/mod-timeout",flagcd);
      if (flagcd == 'B') {
        encodeB("",0,&line,2);
        qmail_put(&qq,line.s,line.len);
      }

      if (flagmime) {
	hdr_boundary(0);
	hdr_ctype(CTYPE_MESSAGE);
        qmail_puts(&qq,"\n");
      }

      if (seek_begin(fd) == -1)
        strerr_die2sys(111,FATAL,MSG1(ERR_SEEK,d));

      substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf));
      if (qmail_copy(&qq,&sstext,-1) != 0) die_read();
      close (fd);

      if (flagmime)
	hdr_boundary(1);

      if (!stralloc_copy(&line,&outlocal)) die_nomem();
      if (!stralloc_cats(&line,"-return-@")) die_nomem();
      if (!stralloc_cat(&line,&outhost)) die_nomem();
      if (!stralloc_0(&line)) die_nomem();
      qmail_from(&qq,line.s);		/* sender */
        qmail_to(&qq,to.s);

     if (*(err = qmail_close(&qq)) != '\0')
       strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ", err + 1);

     strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0;
     strerr_warn2("ezmlm-clean: info: qp ",strnum,0);
}
Beispiel #22
0
void main(int argc,char **argv)
{
  char *sender;
  char *def;
  char *local;
  char *action;
  int flaginheader;
  int flagcomment;
  int flaggoodfield;
  int flagdone;
  int fd, fdlock;
  int match;
  const char *err;
  char encin = '\0';
  unsigned int start,confnum;
  unsigned int pos,i;
  int child;
  int opt;
  char *cp,*cpnext,*cpfirst,*cplast,*cpafter;

  (void) umask(022);
  sig_pipeignore();
  when = now();

  if (!stralloc_copys(&sendopt,"-")) die_nomem();
  opt = getconfopt(argc,argv,options,1,&dir);

  sender = get_sender();
  if (!sender) strerr_die2x(100,FATAL,MSG(ERR_NOSENDER));
  local = env_get("LOCAL");
  if (!local) strerr_die2x(100,FATAL,MSG(ERR_NOLOCAL));
  def = env_get("DEFAULT");
  if (!def) strerr_die2x(100,FATAL,MSG(ERR_NODEFAULT));

  if (!*sender)
    strerr_die2x(100,FATAL,MSG(ERR_BOUNCE));
  if (!sender[str_chr(sender,'@')])
    strerr_die2x(100,FATAL,MSG(ERR_ANONYMOUS));
  if (str_equal(sender,"#@[]"))
    strerr_die2x(100,FATAL,MSG(ERR_BOUNCE));

  /* local should be >= def, but who knows ... */
  cp = local + str_len(local) - str_len(def) - 2;
  if (cp < local) die_badformat();
  action = local + byte_rchr(local,cp - local,'-');
  if (action == cp) die_badformat();
  action++;

  if (!action[0]) die_badformat();
  if (!str_start(action,ACTION_ACCEPT) && !str_start(action,ACTION_REJECT))
    die_badformat();
  start = str_chr(action,'-');
  if (!action[start]) die_badformat();
  confnum = 1 + start + str_chr(action + start + 1,'.');
  if (!action[confnum]) die_badformat();
  confnum += 1 + str_chr(action + confnum + 1,'.');
  if (!action[confnum]) die_badformat();
  if (!stralloc_copyb(&fnbase,action+start+1,confnum-start-1)) die_nomem();
  if (!stralloc_0(&fnbase)) die_nomem();
  cookie(hash,key.s,key.len,fnbase.s,"","a");
  if (byte_diff(hash,COOKIE,action+confnum+1))
    die_badformat();

  fdlock = lockfile("mod/lock");

  switch(checkfile(fnbase.s)) {
    case 0:
      strerr_die2x(100,FATAL,MSG(ERR_MOD_TIMEOUT));
    case -1:			/* only error if new request != action taken */
      if (str_start(action,ACTION_ACCEPT))
        strerr_die2x(0,INFO,MSG(ERR_MOD_ACCEPTED));
      else
        strerr_die2x(100,FATAL,MSG(ERR_MOD_ACCEPTED));
    case -2:
      if (str_start(action,ACTION_REJECT))
        strerr_die2x(0,INFO,MSG(ERR_MOD_REJECTED));
      else
        strerr_die2x(100,FATAL,MSG(ERR_MOD_REJECTED));
    default:
      break;
  }
/* Here, we have an existing filename in fnbase with the complete path */
/* from the current dir in fnmsg. */

  if (str_start(action,ACTION_REJECT)) {

    if (qmail_open(&qq, (stralloc *) 0) == -1)
      strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE));


				/* Build recipient from msg return-path */
    fd = open_read(fnmsg.s);
    if (fd == -1) {
      if (errno != error_noent)
        strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,fnmsg.s));
      else
        strerr_die2x(100,FATAL,MSG(ERR_MOD_TIMEOUT));
    }
    substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf));

    if (getln(&sstext,&line,&match,'\n') == -1 || !match)
      strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
    maketo();			/* extract SENDER from return-path */
						/* Build message */
    hdr_add2s("Mailing-List: ",MSG(TXT_MAILING_LIST));
    if (listid.len > 0)
      hdr_add2("List-ID: ",listid.s,listid.len);
    hdr_datemsgid(when);
    hdr_from("-owner");
    if (replyto)
      hdr_add2s("Reply-To: ",replyto);
    hdr_add2s("To: ",to.s);
    hdr_subject(MSG(SUB_RETURNED_POST));

    if (flagmime) {
      hdr_mime(CTYPE_MULTIPART);
      hdr_boundary(0);
      hdr_ctype(CTYPE_TEXT);
      hdr_transferenc();
    }
    copy(&qq,"text/top",flagcd);
    copy(&qq,"text/mod-reject",flagcd);

    flagcomment = 0;
    flaginheader = 1;
    if (!stralloc_copys(&text,"")) die_nomem();
    if (!stralloc_ready(&text,1024)) die_nomem(); 
    for (;;) {		/* copy moderator's rejection comment */
      if (getln(subfdin,&line,&match,'\n') == -1)
        strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
      if (!match) break;
      if (flaginheader) {
        if (case_startb(line.s,line.len,"Content-Transfer-Encoding:")) {
          pos = 26;
          while (line.s[pos] == ' ' || line.s[pos] == '\t') ++pos;
          if (case_startb(line.s+pos,line.len-pos,"base64"))
            encin = 'B';
          else if (case_startb(line.s+pos,line.len-pos,"quoted-printable"))
            encin = 'Q';
        }
        if (line.len == 1)
          flaginheader = 0;
      } else
        if (!stralloc_cat(&text,&line)) die_nomem();
    }	/* got body */
    if (encin) {
      if (encin == 'B')
        decodeB(text.s,text.len,&line);
      else
        decodeQ(text.s,text.len,&line);
      if (!stralloc_copy(&text,&line)) die_nomem();
    }
    cp = text.s;
    cpafter = text.s + text.len;
    if (!stralloc_copys(&line,"\n>>>>> -------------------- >>>>>\n"))
			die_nomem();
    flaggoodfield = 0;
    flagdone = 0;
    while ((cpnext = cp + byte_chr(cp,cpafter-cp,'\n')) != cpafter) {
      i = byte_chr(cp,cpnext-cp,'%');
      if (i <= 5 && cpnext-cp-i >= 3) {
				/* max 5 "quote characters" and space for %%% */
        if (cp[i+1] == '%' && cp[i+2] == '%') {
          if (!flaggoodfield) {					/* Start tag */
            if (!stralloc_copyb(&quoted,cp,i)) die_nomem();	/* quote chars*/
            flaggoodfield = 1;
            cp = cpnext + 1;
            cpfirst = cp;
            continue;
          } else {						/* end tag */
            if (flagdone)	/* 0 no comment lines, 1 comment line */
              flagdone = 2;	/* 2 at least 1 comment line & end tag */
            break;
          }
        }
      }
      if (flaggoodfield) {
        cplast = cpnext - 1;
        if (*cplast == '\r')	/* CRLF -> '\n' for base64 encoding */
          *cplast = '\n';
        else
          ++cplast;
			/* NUL is now ok, so the test for it was removed */
        flagdone = 1;
        i = cplast - cp + 1;
        if (quoted.len && quoted.len <= i &&
		!str_diffn(cp,quoted.s,quoted.len)) {	/* quote chars */
          if (!stralloc_catb(&line,cp+quoted.len,i-quoted.len)) die_nomem();
        } else
          if (!stralloc_catb(&line,cp,i)) die_nomem();	/* no quote chars */
      }
      cp = cpnext + 1;
    }
    if (flagdone == 2) {
    if (!stralloc_cats(&line,"<<<<< -------------------- <<<<<\n")) die_nomem();
      code_qput(line.s,line.len);
    }
    if (flagcd == 'B') {
      encodeB("",0,&line,2);
      qmail_put(&qq,line.s,line.len);
    }
    if (flagmime) {
      hdr_boundary(0);
      hdr_ctype(CTYPE_MESSAGE);
    }
    qmail_puts(&qq,"\n");
    if (seek_begin(fd) == -1)
      strerr_die2sys(111,FATAL,MSG1(ERR_SEEK,fnmsg.s));

    substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf));
    if (qmail_copy(&qq,&sstext,-1) != 0)
      strerr_die2sys(111,FATAL,MSG1(ERR_READ,fnmsg.s));
    close(fd);

    if (flagmime)
      hdr_boundary(1);

    if (!stralloc_copy(&line,&outlocal)) die_nomem();
    if (!stralloc_cats(&line,"-return-@")) die_nomem();
    if (!stralloc_cat(&line,&outhost)) die_nomem();
    if (!stralloc_0(&line)) die_nomem();
    qmail_from(&qq,line.s);
    if (to.len)
      qmail_to(&qq,to.s);

    if (!stralloc_copys(&fnnew,"mod/rejected/")) die_nomem();
    if (!stralloc_cats(&fnnew,fnbase.s)) die_nomem();
    if (!stralloc_0(&fnnew)) die_nomem();

/* this is strictly to track what happended to a message to give informative */
/* messages to the 2nd-nth moderator that acts on the same message. Since    */
/* this isn't vital we ignore errors. Also, it is no big ideal if unlinking  */
/* the old file fails. In the worst case it gets acted on again. If we issue */
/*  a temp error the reject will be redone, which is slightly worse.         */

    if (*(err = qmail_close(&qq)) == '\0') {
        fd = open_trunc(fnnew.s);
        if (fd != -1)
          close(fd);
        unlink(fnmsg.s);
        strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0;
        strerr_die2x(0,"ezmlm-moderate: info: qp ",strnum);
    } else
        strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1);

  } else if (str_start(action,ACTION_ACCEPT)) {
        fd = open_read(fnmsg.s);
        if (fd == -1) {
          if (errno !=error_noent)
            strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,fnmsg.s));
          else	/* shouldn't happen since we've got lock */
            strerr_die3x(100,FATAL,fnmsg.s,MSG(ERR_MOD_TIMEOUT));
	}

    substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf));
				/* read "Return-Path:" line */
    if (getln(&sstext,&line,&match,'\n') == -1 || !match)
      strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
    maketo();			/* extract SENDER to "to" */
    env_put2("SENDER",to.s);	/* set SENDER */
    if (seek_begin(fd) == -1)	/* rewind, since we read an entire buffer */
      strerr_die2sys(111,FATAL,MSG1(ERR_SEEK,fnmsg.s));

    if ((child = wrap_fork()) == 0) {
      close(0);
      dup(fd);	/* make fnmsg.s stdin */
      if (argc > opt + 1)
	wrap_execvp((const char **)argv + opt);
      else if (argc > opt)
        wrap_execsh(argv[opt]);
      else
        wrap_execbin("/ezmlm-send", &sendopt, dir);
    }
      /* parent */
      close(fd);
      wrap_exitcode(child);
      if (!stralloc_copys(&fnnew,"mod/accepted/")) die_nomem();

      if (!stralloc_cats(&fnnew,fnbase.s)) die_nomem();
      if (!stralloc_0(&fnnew)) die_nomem();
/* ignore errors */
      fd = open_trunc(fnnew.s);
      if (fd != -1)
        close(fd);
      unlink(fnmsg.s);
      _exit(0);
   }
}