Example #1
0
static char *rewrite_env_sender(const char *from)
{
const char *host;

	if (!from)
	{
		if ((from=env("MAILSUSER")) == 0 &&
			(from=env("MAILUSER")) == 0 &&
			(from=env("LOGNAME")) == 0 &&
			(from=env("USER")) == 0)
		{
		struct passwd *pw=mypwd();

			from=pw ? pw->pw_name:"nobody";
		}

		if ((host=env("MAILSHOST")) != 0 ||
			(host=env("MAILHOST")) != 0)
		{
		char	*p=courier_malloc(strlen(from)+strlen(host)+2);

			return (strcat(strcat(strcpy(p, from), "@"), host));
		}
	}
	return (strcpy(courier_malloc(strlen(from)+1), from));
}
Example #2
0
static char *sts_download(const char *domain)
{
	char *url=courier_malloc(strlen(domain)+100);
	char *policy;
	char *v;
	struct sts_id temp_sts;

	if (!url)
		return 0;

	sprintf(url, "https://mta-sts.%s/.well-known/mta-sts.txt", domain);

	policy=sts_download1(url);
	free(url);

	memset(&temp_sts, 0, sizeof(temp_sts));

	temp_sts.policy=policy;

	v=find_in_policy(&temp_sts, "version");

	if (!v || strcmp(v, "STSv1"))
	{
		free(policy);
		policy=0;
	}
	return policy;
}
Example #3
0
static void start_child(unsigned i, char *line, char **cols)
{
int	pipebuf[2];
const char *hostp;
size_t	hostplen;
pid_t	pid;

	hostp=MODULEDEL_HOST(cols);
	for (hostplen=0; hostp[hostplen] &&
		hostp[hostplen] != '\t'; hostplen++)
		;

	if (info[i].host)	free(info[i].host);
	memcpy(info[i].host=courier_malloc(hostplen+1), hostp, hostplen);
	info[i].host[hostplen]=0;

	if (pipe(pipebuf) < 0)	clog_msg_errno();

	pid=module_fork_noblock(0, &i);

	if (pid == 0)
	{
	unsigned	j;
	char	buf[MAXLONGSIZE+1];
	char *p;

		dup2(pipebuf[0], 0);
		close(pipebuf[0]);
		close(pipebuf[1]);
		fclose(childresultpipe);
		dup2(completionpipe[1], 1);
		close(completionpipe[1]);
		close(completionpipe[0]);
		for (j=0; j<module_nchildren; j++)
			if (info[j].cmdpipe >= 0)
				close(info[j].cmdpipe);

		for (j=0; MODULEDEL_HOST(cols)[j]; j++)
			if (MODULEDEL_HOST(cols)[j] == '\t')
			{
				MODULEDEL_HOST(cols)[j]=0;
				break;
			}

		p=buf+MAXLONGSIZE;
		*p=0;
		do
		{
			* --p = '0' + (i % 10);
		} while ( (i=i / 10) != 0);

		execl("courieresmtp", "courieresmtp", p,
			MODULEDEL_HOST(cols), (char *)0);
		clog_msg_errno();
		_exit(1);
	}
	info[i].pid=pid;
	close (pipebuf[0]);
	info[i].cmdpipe=pipebuf[1];
}
Example #4
0
int	AliasSearch::Search(const char *address, AliasHandler &h)
{
char	*p=0;
const char *q;
char	*hostdomain=0;

	q=strrchr(address, '@');

	/* islocal checks both local domains, and hosted domains,
	** we want to replace domain with 'me' only for local domains.
	*/
	if (!q || (config_islocal(q+1, &hostdomain) && hostdomain == 0))
					/*
					** Make sure we look for aliases for
					** "me"
					*/
	{
		const char *me=config_defaultdomain();
		char *r;

		if (!q)
			q=address+strlen(address);

		p=(char *)courier_malloc(q-address+2+strlen(me));
		if (!p)	clog_msg_errno();
		memcpy(p, address, q-address);
		strcat(strcpy(&p[q-address], "@"), me);
		r=udomainlower(p);	/* For stupid people */
		free(p);
		p=r;
		address=p;
	}
	if (hostdomain)	free(hostdomain);

	if (Try(module_record, address, h) == 0 &&
		TryVirtual(module_record, address, &h) == 0 &&
		Try(local_record, address, h) == 0 &&
		TryVirtual(local_record, address, &h) == 0)
	{
		int rc;

#if HAVE_LDAP
		if (p)
			*strrchr(p, '@')=0;
		// Strip local domain from addresses passed to aliasd

		rc=TryAliasD(address, &h);
#else
		rc=1;
#endif
		if (p)	free(p);
		return (rc);
	}
	if (p)	free(p);
	return (0);
}
Example #5
0
static char *get_gecos()
{
struct passwd *pw=mypwd();
char	*p, *q;

	if (!pw || !pw->pw_gecos)	return (0);

	p=strcpy(courier_malloc(strlen(pw->pw_gecos)+1), pw->pw_gecos);

	if ((q=strchr(p, ',')) != 0)	*q=0;
	return (p);
}
Example #6
0
void qmsgunlink(ino_t n, time_t rightnow)
{
	const char *bigbrother=getenv("ARCHIVEDIR");

	if (bigbrother && *bigbrother)
	{
		struct tm *tmptr=localtime(&rightnow);

		/* Archive this message */

		if (tmptr)
		{
			const char *dname=qmsgsdatname(n);
			const char *tname=strrchr(dname, '/');

			char *p=courier_malloc(strlen(bigbrother)+
					       strlen(tname)+40);

			sprintf(p, "%s/%04d.%02d.%02d%s",
				bigbrother, tmptr->tm_year + 1900,
				tmptr->tm_mon+1,
				tmptr->tm_mday, tname);

			if (bigbrother_create_rename(dname, p) == 0)
			{
				dname=qmsgsctlname(n);

				strcpy(strrchr(p, '/'), strrchr(dname, '/'));

				if (rename(dname, p) == 0)
				{
					free(p);
					return;
				}
			}

			clog_msg_start_err();
			clog_msg_str("Unable to move ");
			clog_msg_str(dname);
			clog_msg_str(" to ");
			clog_msg_str(p);
			clog_msg_send();
			clog_msg_prerrno();

			free(p);
		}
	}

	unlink(qmsgsdatname(n));
	unlink(qmsgsctlname(n));
}
Example #7
0
char *ulocallower(const char *c)
{
	static int islocallower=0;

	if (islocallower == 0)
	{
		char	*s=config_localfilename("locallowercase");

		islocallower = access(s, 0) == 0 ? 1:-1;
		free(s);
	}

	if ( islocallower > 0 || (
#if     HAVE_STRNCASECMP
		strncasecmp(c, "postmaster", 10)
#else
		strnicmp(c, "postmaster", 10)
#endif
			== 0 && (c[10] == '\0' || c[10] == '@')))
	{
		char *c_copy=courier_strdup(c);
		char *at=strchr(c_copy, '@');
		char save;
		char *lower_username;

		if (!at)
			at=c_copy+strlen(c_copy);

		save=*at;
		*at=0;

		lower_username=	unicode_convert_tocase(c_copy, "utf-8",
						       unicode_lc, unicode_lc);
		*at=save;

		if (lower_username)
		{
			char *buf=courier_malloc(strlen(lower_username)+
						 strlen(at)+1);

			strcat(strcpy(buf, lower_username), at);
			free(c_copy);
			free(lower_username);
			return buf;
		}
		free(c_copy);
	}

	return courier_strdup(c);
}
Example #8
0
static void add2header(const char *p, unsigned l, struct rwmsginfo *msginfo)
{
	if (l + msginfo->headerbuflen > msginfo->headerbufsize)
	{
	unsigned ll=(msginfo->headerbufsize + l + 1023) & ~1023;
	char	*buf=courier_malloc(ll);

		if (msginfo->headerbufsize)
			memcpy(buf, msginfo->headerbuf, msginfo->headerbufsize);
		if (msginfo->headerbuf)	free(msginfo->headerbuf);
		msginfo->headerbuf=buf;
		msginfo->headerbufsize=ll;
	}
	memcpy(msginfo->headerbuf+msginfo->headerbuflen, p, l);
	msginfo->headerbuflen += l;
}
Example #9
0
char *config_dsnfrom()
{
char	*f=config_search("dsnfrom");
char	*p=config_read1l(f);
static const char defaultdsnfrom[]="\"Courier mail server at %s\" <@>";

	free(f);
	if (!p)
	{
	const char *me=config_me();

		p=courier_malloc(sizeof(defaultdsnfrom)+strlen(me));
		sprintf(p, defaultdsnfrom, me);
	}
	return (p);
}
Example #10
0
static void do_rw_rewrite_chksyn_print(struct rw_info *info,
				       struct rfc822token *t)
{
	if (rw_syntaxchk(t))
	{
	static const char errmsg[]="Syntax error: ";
	char	*addr=rfc822_gettok(info->ptr);
	char	*buf;

		if (!addr)	clog_msg_errno();
		buf=courier_malloc(strlen(addr)+sizeof(errmsg));
		strcat(strcpy(buf, errmsg), addr);
		free(addr);
		(*info->err_func)(553, buf, info);
		free(buf);
	}
	else
		rw_rewrite_print(info);
}
Example #11
0
static char *policy_filename_for_domain(const char *domain)
{
	char *filename;
	char *p;

	if (strchr(domain, '/'))
		return 0;

	if ((filename=courier_malloc(strlen(domain)+sizeof(STSDIR "/")))
	    == NULL)
		return 0;

	strcat(strcpy(filename, STSDIR "/"), domain);

	for (p=filename+sizeof(STSDIR); *p; ++p)
		if (*p >= 'A' && *p <= 'Z')
		*p += 'a'-'A';

	return filename;
}
Example #12
0
char *config_dsnfrom()
{
char	*f=config_localfilename("dsnfrom");
char	*p=config_read1l(f);
static const char defaultdsnfrom[]="Courier mail server at %s <@>";

	free(f);
	if (!p)
	{
		const char *me=config_me();
		char *me_encoded=rfc2047_encode_str(me,
						    RFC2045CHARSET,
						    rfc2047_qp_allow_word);

		if (me_encoded)
			me=me_encoded;
		p=courier_malloc(sizeof(defaultdsnfrom)+strlen(me));
		sprintf(p, defaultdsnfrom, me);
		if (me_encoded)
			free(me_encoded);
	}
	return (p);
}
Example #13
0
char *udomainlower(const char *c)
{
	const char *d;
	char *ud;
	char *s;

	d=strchr(c, '@');

	if (!d)
		return courier_strdup(c);

	ud=unicode_convert_tocase(++d, "utf-8", unicode_lc, unicode_lc);

	if (!ud)
		return courier_strdup(c);

	s=courier_malloc(strlen(ud)+1+(d-c));

	memcpy(s, c, d-c);
	strcpy(s+(d-c), ud);
	free(ud);
	return s;
}
Example #14
0
static char *udomainace2(const char *c)
{
	const char *d;
	char *ud;
	char *s;

	d=strchr(c, '@');

	if (!d)
		return courier_strdup(c);

	++d;
	if (idna_to_ascii_8z(d, &s, 0) != IDNA_SUCCESS)
	{
		return courier_strdup(c);
	}

	ud=courier_malloc((d-c+1)+strlen(s));

	memcpy(ud, c, d-c);
	strcpy(ud+(d-c), s);
	free(s);
	return ud;
}
Example #15
0
char	*config_localfilename(const char *p)
{
char	*c=courier_malloc(sizeof(SYSCONFDIR "/")+strlen(p));

	return (strcat(strcpy(c, SYSCONFDIR "/"), p));
}
Example #16
0
static void dofwd(const char *addr, const char *from, const char *fromuser,
	const char *origuser)
{
	if (!submit_started)
	{
	char	*args[5];

	static const char *envvars[]={
		"DSNNOTIFY",
		"DSNRET",
		"NOADDATE",
		"NOADDMSGID",
		"MIME",
		0};

	char	*envs[sizeof(envvars)/sizeof(envvars[0])];
	int	i, j;

		for (i=j=0; envvars[i]; i++)
		{
		const char *p=getenv(envvars[i]);
		char	*q;

			if (!p)	continue;
			q=strcat(strcat(strcpy(courier_malloc(
					strlen(envvars[i])+strlen(p)+2),
					envvars[i]), "="), p);
			envs[j]=q;
			j++;
		}
		envs[j]=0;


		args[0]="submit";
		args[1]="local";
		args[2]="dns; localhost (localhost [127.0.0.1])";
		args[3]=strcat(strcpy(courier_malloc(
				sizeof("forwarded by ")+strlen(fromuser)),
					"forwarded by "), fromuser);
		args[4]=0;

		errptr=errbuf;
		errleft=sizeof(errbuf)-1;

		save_submit_errmsg("The following error occured when trying to forward this message: \n");
		strcpy(errptr, "UNKNOWN ERROR - no further description is available");

		if (submit_fork(args, envs, save_submit_errmsg) ||
			(submit_write_message(from), submit_readrcprinterr()))
		{
			submit_err=1;
			return;
		}
		while (j)
		{
			free(envs[--j]);
		}
		submit_err=0;
		submit_started=1;
	}

	if (!submit_err)
	{
	char	*p;

		p=strcat(strcat(strcpy(courier_malloc(
			strlen(addr)+strlen(origuser)+4), addr),
				"\tF\t"), origuser);
		submit_write_message(p);
		free(p);
		if (submit_readrcprinterr())
		{
			submit_err=1;
		}
	}
}
Example #17
0
static int sts_policy_override2(struct sts_id *id,
				const char *domain,
				const char *policy_filename,
				FILE *cached_policy_fp,
				int readwrite,
				void *mode_ptr)
{
	char *new_policy;

	if (!cached_policy_fp || load(id, cached_policy_fp))
	{
		printf("%s: cached policy not found.\n", domain);
	}
	else if (!readwrite)
	{
		printf("%s: no write permission.\n", policy_filename);
	}
	else if ((new_policy=courier_malloc(strlen(id->policy)+
					    strlen(domain)+1024)) != 0)
	{
		char *put_p=new_policy;
		const char *p;
		char lastc='\n';
		int skipping=0;

		for (p=id->policy; *p; p++)
		{
			if (lastc == '\n')
				skipping=strncmp(p, "mode:", 5) == 0 ||
					strncmp(p, "info:", 5) == 0;

			if (!skipping)
				*put_p++=*p;

			lastc=*p;
		}
		if (lastc != '\n')
			*put_p++='\n';

		sprintf(put_p,
			"info: this policy has been manually overridden, "
			"as follows\n"
			"info: use \"testmxlookup --sts-purge %s\" to "
			"restore the default policy:\n",
			domain);

		switch (*(enum sts_mode *)mode_ptr) {
		case sts_mode_none:
			strcat(put_p, "mode: none\n");
			break;
		case sts_mode_testing:
			strcat(put_p, "mode: testing\n");
			break;
		case sts_mode_enforce:
			strcat(put_p, "mode: enforce\n");
			break;
		}
		free(id->policy);
		id->policy=new_policy;
		save(id, cached_policy_fp);
	}
	return 0;
}
Example #18
0
int main(int argc, char **argv)
{
    if (argc > 1 && strcmp(argv[1], "--version") == 0)
    {
        printf("%s\n", COURIER_COPYRIGHT);
        exit(0);
    }

    if (chdir(courierdir()))
    {
        perror("chdir");
        return (1);
    }
    if (argc < 2)	return (0);

    if (strcmp(argv[1], "stop") == 0)
    {
        int	fd;

        trigger(TRIGGER_STOP);

        /* Wait until the exclusive lock goes away: */

        signal(SIGHUP, SIG_DFL);
        if ((fd=open(TMPDIR "/courierd.lock", O_RDWR|O_CREAT, 0600))
                < 0)	clog_msg_errno();

        alarm(15);	/* But abort after 15 seconds. */

        ll_lock_ex(fd);
        return (0);
    }

    if (strcmp(argv[1], "restart") == 0)
    {
        trigger(TRIGGER_RESTART);
        return (0);
    }

    if (strcmp(argv[1], "flush") == 0)
    {
        ino_t	n;
        struct	ctlfile	ctf;

        if (getuid())
        {
            /*
            ** We'll fail trying to open the pipe anyway, but let's
            ** give a meaningful error message now.
            */
            fprintf(stderr,
                    "courier flush can be executed only by the superuser.\n");
            exit(1);
        }

        if (argc < 3)
        {
            trigger(TRIGGER_FLUSH);	/* Everything */
            exit(0);
        }

        if (comparseqid(argv[2], &n) == 0 &&
                ctlfile_openi(n, &ctf, 1) == 0)
        {
            int c=ctlfile_searchfirst(&ctf, COMCTLFILE_MSGID);

            if (c >= 0 && strcmp(ctf.lines[c]+1, argv[2]) == 0)
            {
                char	*s=courier_malloc(sizeof(TRIGGER_FLUSHMSG)+1+
                                          strlen(argv[2]));

                strcat(strcat(strcpy(s, TRIGGER_FLUSHMSG),
                              argv[2]), "\n");
                trigger(s);
                ctlfile_close(&ctf);
                return (0);
            }
            ctlfile_close(&ctf);
        }
        fprintf(stderr, "No such message.\n");
        exit(1);
        return (1);
    }

    /* Might as well... */

    if (strcmp(argv[1], "start") == 0)
    {
        pid_t	p;
        int	waitstat;
        char	dummy;

        /*
        ** Ok, courierd will close file descriptor 3 when it starts, so we
        ** put a pipe on there, and wait for it to close.
        */
        int	pipefd[2];

        close(3);
        if (open("/dev/null", O_RDONLY) != 3 || pipe(pipefd))
        {
            fprintf(stderr, "Cannot open pipe\n");
            exit(1);
        }

        if (getuid())
        {
            /*
            ** We'll fail trying to execute courierd anyway, but let's
            ** give a meaningful error message now.
            */
            fprintf(stderr, "courier start can be executed only by the superuser.\n");
            return (1);
        }
        signal(SIGCHLD, SIG_DFL);
        while ((p=fork()) == -1)
        {
            perror("fork");
            sleep(10);
        }
        if (p == 0)
        {
            dup2(pipefd[1], 3);
            close(pipefd[1]);
            close(pipefd[0]);
            while ((p=fork()) == -1)
            {
                perror("fork");
                sleep(10);
            }
            if (p == 0)
            {
                /*
                ** stdin from the bitbucket.  stdout to
                ** /dev/null, or the bitbucket.
                */

                signal(SIGHUP, SIG_IGN);
                close(0);
                open("/dev/null", O_RDWR);
                dup2(0, 1);
                dup2(0, 2);
                /* See if we can disconnect from the terminal */

#ifdef	TIOCNOTTY
                {
                    int fd=open("/dev/tty", O_RDWR);

                    if (fd >= 0)
                    {
                        ioctl(fd, TIOCNOTTY, 0);
                        close(fd);
                    }
                }
#endif
                /* Remove any process groups */

#if	HAVE_SETPGRP
#if	SETPGRP_VOID
                setpgrp();
#else
                setpgrp(0, 0);
#endif
#endif
                execl( DATADIR "/courierctl.start",
                       "courierctl.start", (char *)0);
                perror("exec");
                _exit(1);
            }
            _exit(0);
        }
        close(pipefd[1]);
        while (wait(&waitstat) != p)
            ;
        if (read(pipefd[0], &dummy, 1) < 0)
            ; /* ignore */
        close(pipefd[0]);
        close(3);
        return (0);
    }

    if (strcmp(argv[1], "clear") == 0 && argc > 2)
    {
        libmail_changeuidgid(MAILUID, MAILGID);

        if (strcmp(argv[2], "all") == 0)
        {
            courier_clear_all();
        }
        else
        {
            track_save(argv[2], TRACK_ADDRACCEPTED);
            printf("%s cleared.\n", argv[2]);
        }
        return (0);
    }

    if (argc > 2 && strcmp(argv[1], "show") == 0 &&
            strcmp(argv[2], "all") == 0)
    {
        libmail_changeuidgid(MAILUID, MAILGID);
        courier_show_all();
    }

    return (0);
}
Example #19
0
static void rewrite_headers(const char *From)
{
int	seen_from=0;
char	headerbuf[5000];
int	c, i;
const char *mailuser, *mailuser2, *mailhost;
char	*p;
char	*pfrom=From ? strcpy(courier_malloc(strlen(From)+1), From):0;

	if ((mailuser=env("MAILUSER")) == 0 &&
		(mailuser=env("LOGNAME")) == 0)
		mailuser=env("USER");
	mailuser2=env("MAILUSER");
	mailhost=env("MAILHOST");

	while (fgets(headerbuf, sizeof(headerbuf), stdin))
	{
	char	*p=strchr(headerbuf, '\n');

		if (p)
		{
			*p=0;
			if (p == headerbuf || strcmp(headerbuf, "\r") == 0)
				break;
		}

#if HAVE_STRNCASECMP
		if (strncasecmp(headerbuf, "from:", 5))
#else
		if (strnicmp(headerbuf, "from:", 5))
#endif
		{
			fprintf(submit_to, "%s", headerbuf);
			if (!p)
				while ((c=getchar()) != EOF && c != '\n')
					putc(c, submit_to);
			putc('\n', submit_to);
			continue;
		}
		if (!p)
			while ((c=getchar()) != EOF && c != '\n')
				;	/* I don't care */
		if (seen_from)	continue;	/* Screwit */
		seen_from=1;

		i=strlen(headerbuf);
		for (;;)
		{
			c=getchar();
			if (c != EOF)	ungetc(c, stdin);
			if (c == EOF || c == '\r' || c == '\n')	break;
			if (!isspace((int)(unsigned char)c))	break;
			while ((c=getchar()) != EOF && c != '\n')
			{
				if (i < sizeof(headerbuf)-1)
					headerbuf[i++]=c;
			}
			headerbuf[i]=0;
		}

		p=rewrite_from(headerbuf+5, mailuser2, mailhost, pfrom);
		fprintf(submit_to, "From: %s\n", p);
		free(p);
	}
	if (!seen_from)
	{
		if (!mailuser)
		{
		struct passwd *pw=mypwd();

			mailuser=pw ? pw->pw_name:"nobody";
		}

		if (!pfrom)
		{
			if ( !(From=env("MAILNAME")) && !(From=env("NAME")))
			{
				pfrom=get_gecos();
			}
			else	pfrom=strcpy(courier_malloc(strlen(From)+1),
                                        From);
		}

		p=rewrite_from(NULL, mailuser, mailhost, pfrom);
		fprintf(submit_to, "From: %s\n", p);
		free(p);
	}
	putc('\n', submit_to);
	if (pfrom)	free(pfrom);
}
Example #20
0
static char *rewrite_from(const char *oldfrom, const char *newuser,
	const char *newhost, const char *newname)
{
struct rfc822t *rfct;
struct rfc822a *rfca;
struct rfc822t *usert, *hostt, *namet;
struct rfc822token attoken, **tp;
char	*p;
const char *q;
char	*gecosname=0;

	if (!oldfrom)
	{
	char	*p=courier_malloc(
			(newuser ? strlen(newuser):0)+
			(newhost ? strlen(newhost):0)+4);
		strcpy(p, "<");
		if (newuser)	strcat(p, newuser);
		if (newuser && newhost)
			strcat(strcat(p, "@"), newhost);
		strcat(p, ">");
		if (newname)
		{
		char *q, *r;

			namet=tokenize_name(newname);
			q=rfc822_gettok(namet->tokens);
			rfc822t_free(namet);
			r=courier_malloc(strlen(p)+strlen(q)+2);
			strcat(strcat(strcpy(r, q), " "), p);
			free(p);
			p=r;
			free(q);
		}
		return (p);
	}

	if ((rfct=rfc822t_alloc_new(oldfrom, NULL, NULL)) == 0 ||
		(rfca=rfc822a_alloc(rfct)) == 0)
	{
		clog_msg_errno();
		return(0);
	}

	if ((q=env("MAILNAME")) || (q=env("NAME")))
		newname=q;

	if (!newname && rfca->naddrs == 0)
		newname=gecosname=get_gecos();

	if ((rfca->naddrs == 0 || rfca->addrs[0].tokens == 0) && newuser == 0)
	{
	struct	passwd *pw=mypwd();

		if (pw)	newuser=pw->pw_name;
	}

	namet=newname ? tokenize_name(newname):0;
	usert=newuser ? rw_rewrite_tokenize(newuser):0;
	hostt=newhost ? rw_rewrite_tokenize(newhost):0;

	if (rfca->naddrs == 0 || rfca->addrs[0].tokens == 0)
	{
	struct rfc822addr a;
	struct rfc822a	fakea;

		if (hostt)
		{
		struct rfc822token *t;

			attoken.token='@';
			attoken.next=hostt->tokens;
			attoken.ptr=0;
			attoken.len=0;

			for (t=usert->tokens; t->next; t=t->next)
				;
			t->next=&attoken;
		}
		fakea.naddrs=1;
		fakea.addrs= &a;

		if (!namet)	namet=tokenize_name("");
		if (!usert)	usert=rw_rewrite_tokenize("");
		a.name=namet->tokens;
		a.tokens=usert->tokens;
		p=rfc822_getaddrs(&fakea);
	}
	else
	{
	struct	rfc822token *t, *u;

		rfca->naddrs=1;
		if (usert)
		{
			for (t=rfca->addrs[0].tokens; t; t=t->next)
				if (t->token == '@')	break;
			
			for (u=usert->tokens; u->next; u=u->next)
				;
			u->next=t;
			rfca->addrs[0].tokens=usert->tokens;;
		}

		if (hostt && rfca->addrs[0].tokens)
		{
			for (tp= &rfca->addrs[0].tokens; *tp;
				tp= &(*tp)->next)
				if ( (*tp)->token == '@')	break;
			*tp=&attoken;
			attoken.token='@';
			attoken.next=hostt->tokens;
			attoken.ptr=0;
			attoken.len=0;
		}
		if (namet)
			rfca->addrs[0].name=namet->tokens;

		p=rfc822_getaddrs(rfca);
	}

	if (!p)	clog_msg_errno();

	if (usert)	rfc822t_free(usert);
	if (hostt)	rfc822t_free(hostt);
	if (namet)	rfc822t_free(namet);
	rfc822t_free(rfct);
	rfc822a_free(rfca);
	if (gecosname)	free(gecosname);
	return (p);
}
Example #21
0
static char *fetch_smtproutes(const char *domain)
{
char	*buf=get_control_smtproutes();
const char *p=buf;

	if (!buf)
	{
	struct dbobj d;
	char	*p, *q;
	size_t	l;

		p=config_search("esmtproutes.dat");

		dbobj_init(&d);
		if (dbobj_open(&d, p, "R"))
		{
			free(p);
			return (0);
		}
		free(p);
		p=strcpy(courier_malloc(strlen(domain)+1), domain);
		for (q=p; *q; q++)
			*q=tolower(*q);
		q=dbobj_fetch(&d, p, strlen(p), &l, "D");
		free(p);
		dbobj_close(&d);
		if (!q)	return (0);
		p=courier_malloc(l+1);
		memcpy(p, q, l);
		p[l]=0;
		free(q);
		return (p);
	}

	while (*p)
	{
	unsigned i;

		for (i=0; p[i] && p[i] != '\n' && p[i] != '\r' && p[i] != ':';
			++i)
			;

		if (p[i] == ':' && (i == 0 ||
			config_domaincmp(domain, p, i) == 0))
		{
		char *q;

			p += i;
			++p;
			for (i=0; p[i] && p[i] != '\n' && p[i] != '\r'; i++)
				;

			while (i && isspace((int)(unsigned char)p[i-1]))
				--i;
			while (i && isspace((int)(unsigned char)*p))
			{
				++p;
				--i;
			}
			if (i == 0)
			{
				free(buf);
				return (0);
			}

			q=courier_malloc(i+1);
			memcpy(q, p, i);
			q[i]=0;
			free(buf);
			return (q);
		}

		while (p[i])
		{
			if (p[i] == '\n' || p[i] == '\r')
			{
				++i;
				break;
			}
			++i;
		}
		p += i;
	}

	free(buf);
	return (0);
}
Example #22
0
static int load2(struct sts_id *id, FILE *fp)
{
	char buffer[1024];
	char *p;
	long pos;
	struct stat stat_buf;
	size_t s;

	if (!fgets(buffer, sizeof(buffer), fp) ||
	    strcmp(buffer, "1\n"))
		return -1;

	if (id->id)
	{
		free(id->id);
		id->id=0;
	}

	id->tempfail=0;
	while (fgets(buffer, sizeof(buffer), fp))
	{
		if (strcmp(buffer, "\n") == 0)
			break;

		if (strcmp(buffer, "tempfail") == 0)
		{
			id->tempfail=1;
		}

		if (strcmp(strtok(buffer, ": "), "id"))
			continue;

		if ((p=strtok(NULL, ": \r\n")) == 0)
			p="";

		if ((id->id=courier_strdup(p)) == 0)
			break;
	}

	if (!id->id)
		return -1;

	while (strcmp(buffer, "\n"))
	{
		if (fgets(buffer, sizeof(buffer), fp) == 0)
			return -1;
	}

	if ((pos=ftell(fp)) < 0 || fstat(fileno(fp), &stat_buf) < 0)
		return -1;

	s=stat_buf.st_size-pos;

	if ((id->policy=courier_malloc(s+1)) == NULL ||
	    fread(id->policy, s, 1, fp) != 1)
		return -1;

	id->policy[s]=0;
	id->timestamp=stat_buf.st_mtime;
	id->expiration=id->timestamp+max_age(id);

	return 0;
}
Example #23
0
int main(int argc, char **argv)
{
const char *from=0;
const char *From=0;
const char *ret=0, *dsn=0, *security=0, *envid=0;
int	argn, argp;
int	errflag=0;
int	c;
char	*args[6];
char	*envs[7];
int	envp;
int	tostdout=0;
char	frombuf[NUMBUFSIZE+30];
int	doverp=0;
int	bcconly=0;
char	ubuf[NUMBUFSIZE];
char	*uucprmail=0;
char	*s;
char	ret_buf[2], security_buf[40];
int     submit_errcode;

	/*
	** Immediately drop uid, force GID to MAILGID
	** The reason we can't just setgid ourselves to MAILGID is because
	** that only sets the effective uid.  We need to also set both
	** real and effective GIDs, otherwise maildrop filtering will fail,
	** because the real gid won't be trusted.
	*/
	setgid(MAILGID);
	setuid(getuid());
	signal(SIGCHLD, SIG_DFL);
	signal(SIGPIPE, SIG_IGN);
	argn=1;

	putenv("AUTHMODULES="); /* See module.local/local.c */

	putenv("LANG=en_US");
	putenv("CHARSET=iso-8859-1");
	putenv("MM_CHARSET=iso-8859-1");

#if HAVE_SETLOCALE
	setlocale(LC_ALL, "C");
#endif

	/* Only uucp can run rmail (this better be installed setgid) */

	if ((s=strrchr(argv[0], '/')) != 0)	++s;
	else	s=argv[0];
	if (strcmp(s, "rmail") == 0)
	{
	struct passwd	*p=mypwd();
	char	*uu_machine, *uu_user;

		if (!p || strcmp(p->pw_name, "uucp"))
		{
			fprintf(stderr, "rmail: permission denied.\n");
			exit(EX_NOPERM);
		}

		uu_machine=getenv("UU_MACHINE");
		uu_user=getenv("UU_USER");

		if (!uu_machine || !uu_user)
		{
			fprintf(stderr,
				"rmail: UU_MACHINE!UU_USER required.\n");
			exit(EX_NOPERM);
		}
		uucprmail=malloc(strlen(uu_machine)+strlen(uu_user)+2);
		if (!uucprmail)
		{
			perror("malloc");
			exit(EX_TEMPFAIL);
		}
		strcat(strcat(strcpy(uucprmail, uu_machine), "!"), uu_user);
	}

	while (argn < argc)
	{
	const char *arg;
	int	c;

		if (argv[argn][0] != '-')	break;

		if (strcmp(argv[argn], "-") == 0)
		{
			++argn;
			break;
		}

		if (uucprmail && strncmp(argv[argn], "-f", 2)

		/*
		** Ok, obviously no UUCP version will give me the following
		** options, must I can hope, can't I?
		*/
			&& strcmp(argv[argn], "-verp")
			&& strncmp(argv[argn], "-N", 2)
			&& strncmp(argv[argn], "-R", 2)
			&& strncmp(argv[argn], "-V", 2)

			/* Ignore the ignorable */

			&& strncmp(argv[argn], "-o", 2)
			&& strncmp(argv[argn], "-t", 2)

			)
		{
			fprintf(stderr, "rmail: invalid option %s\n",
				argv[argn]);
			exit(EX_NOPERM);
		}

		if (strcmp(argv[argn], "-verp") == 0)
		{
			doverp=1;
			++argn;
			continue;
		}

		if (strcmp(argv[argn], "-bcc") == 0)
		{
			bcconly=1;
			++argn;
			continue;
		}

		if (strcmp(argv[argn], "-bs") == 0)
		{
			esmtpd();
		}
		switch (c=argv[argn][1])	{
		case 'o':
		case 'f':
		case 'F':
		case 'R':
		case 'N':
		case 'S':
		case 'V':
			break;
		case 'n':
			tostdout=1;
			++argn;
			continue;
		default:
			++argn;
			continue;
		}
		arg=argv[argn]+2;
		if (!*arg && argn+1 < argc)
			arg=argv[++argn];
		++argn;

		if (c == 'f')
			from=arg;
		else if (c == 'F')
			From=arg;
		else if (c == 'N')
			dsn=arg;
		else if (c == 'S')
		{
			char *q;

			if (strcasecmp(arg, "NONE") &&
			    strcasecmp(arg, "STARTTLS"))
			{
				fprintf(stderr, "sendmail: invalid option"
					" -S %s\n",
					arg);
				exit(EX_NOPERM);
			}
			strcpy(security_buf, arg);

			for (q=security_buf; *q; q++)
				*q=toupper((int)(unsigned char)*q);

			security=security_buf;
		}
		else if (c == 'R')
		{
			ret_buf[0]= toupper((int)(unsigned char)*arg);
			ret_buf[1]= 0;
			ret=ret_buf;
		}
		else if (c == 'V')
			envid=arg;
	}

	sprintf(frombuf, "uid %s", libmail_str_uid_t(getuid(), ubuf));
	argp=0;
	args[argp++]="submit";
	if (bcconly)
		args[argp++]="-bcc";

	if (uucprmail)
	{
		if (argn >= argc)
		{
			fprintf(stderr, "rmail: missing recipients\n");
			exit(EX_NOPERM);
		}

		args[argp++]="uucp";
		s=malloc(sizeof("unknown; uucp ()")+strlen(uucprmail));
		if (!s)
		{
			perror("malloc");
			exit(EX_TEMPFAIL);
		}
		strcat(strcat(strcpy(s, "unknown; uucp ("), uucprmail), ")");
		args[argp++]=s;
	}
	else
	{
		args[argp++]="local";
		args[argp++]="dns; localhost (localhost [127.0.0.1])";
		args[argp++]=frombuf;
	}
	args[argp++]=0;
	envp=0;

	clog_open_stderr("sendmail");
	if (ret || security || doverp)
	{
		envs[envp]=strcat(strcat(strcpy(courier_malloc(strlen(ret ?
			ret:"")+strlen(security ? security:"") + 30),
						"DSNRET="), (ret ? ret:"")),
				  (doverp ? "V":""));
		if (security)
			strcat(strcat(strcat(envs[envp], "S{"),
				      security), "}");

		++envp;
	}

	if (dsn)
	{
		envs[envp]=strcat(strcpy(courier_malloc(strlen(dsn)+11),
			"DSNNOTIFY="), dsn);
		++envp;
	}
	if (envid)
	{
		envs[envp]=strcat(strcpy(courier_malloc(strlen(envid)+10),
			"DSNENVID="), envid);
		++envp;
	}
	envs[envp++]="TCPREMOTEHOST=localhost";
	envs[envp++]="TCPREMOTEIP=127.0.0.1";

	if (!uucprmail)
		envs[envp++]=strcat(strcpy(courier_malloc(strlen(frombuf)+
				sizeof("TCPREMOTEINFO=")),
				"TCPREMOTEINFO="), frombuf);
	envs[envp]=0;

	if (!tostdout && submit_fork(args, envs, submit_print_stdout))
	{
		fprintf(stderr, "sendmail: Service temporarily unavailable.\n");
		exit(EX_TEMPFAIL);
	}

	if (tostdout)
		submit_to=stdout;
	else
	{
		if (uucprmail)
		{
			submit_write_message(from ? from:"");
		}
		else
		{
		char	*p;

			p=rewrite_env_sender(from);
			submit_write_message(p);
			free(p);
		}
		if ((submit_errcode=submit_readrcprinterr()) != 0)
		{
			exit_submit(submit_errcode);
		}
	}

	while (!tostdout && argn < argc)
	{
		submit_write_message(argv[argn]);
		if ((errflag=submit_readrcprinterr()) != 0)
		{
			fprintf(stderr, "%s: invalid address.\n", argv[argn]);
		}
		++argn;
	}
	if (errflag)	exit_submit(errflag);
	if (!tostdout)
		putc('\n', submit_to);

	if (!uucprmail)
		rewrite_headers(From);

	while ((c=getchar()) != EOF)
	{
		putc(c, submit_to);
	}
	fflush(submit_to);
	signal(SIGINT, SIG_IGN);
	signal(SIGTERM, SIG_IGN);
	signal(SIGHUP, SIG_IGN);

	errflag=0;
	if (ferror(submit_to) || (!tostdout && (
		fclose(submit_to) ||
		(errflag=submit_readrcprinterr()) || submit_wait()))
		)
	{
		fprintf(stderr, "sendmail: Unable to submit message.\n");
		if (errflag)
			exit_submit(errflag);
		exit(EX_TEMPFAIL);
	}
	exit(0);
}
Example #24
0
static void fax(struct moduledel *p)
{
	struct	ctlfile ctf;
	unsigned nreceipients=p->nreceipients;
	const char *host=p->host;
	const char *receipient;
	unsigned nrecipient=(unsigned)atol(p->receipients[0]);
	int pipefd[2];
	pid_t child_proc;
	int faxopts;
	int n_cover_pages;
	FILE *fp;

	struct faxconv_err_args err_args;

	struct sort_file_list *page_list, *pp;


#if     HAVE_SETPGRP
#if     SETPGRP_VOID
        setpgrp();
#else
        setpgrp(0, 0);
#endif
#else
#if     HAVE_SETPGID
        setpgid(0, 0);
#endif
#endif

	if (comgetfaxopts(host, &faxopts))
	{
		clog_msg_start_err();
		clog_msg_str("courierfax: FATAL: invalid host");
		clog_msg_send();
		exit(1);
	}

	putenv(faxopts & FAX_LOWRES ? "FAXRES=lo":"FAXRES=hi");

	if (nreceipients != 1)
	{
		clog_msg_start_err();
		clog_msg_str("courierfax: FATAL: # receipients must be 1");
		clog_msg_send();
		exit(1);
	}

	receipient=p->receipients[1];
	nrecipient=(unsigned)atol(p->receipients[0]);

	if (ctlfile_openi(p->inum, &ctf, 0))
		clog_msg_errno();

	/* Convert message to fax format, use a child process */

	signal(SIGTERM, faxabort);

	if (pipe(pipefd) < 0)
	{
		clog_msg_errno();
	}

	child_proc=fork();
	if (child_proc < 0)
	{
		clog_msg_errno();
		return;
	}

	if (child_proc == 0)
	{
		const char *fn;

		close(0);
		if (open("/dev/null", O_RDONLY) != 0)
			clog_msg_errno();

		close(pipefd[0]);
		close(1);
		if (dup(pipefd[1]) != 1)
		{
			perror("dup");
			exit(1);
		}
		close(2);
		if (dup(pipefd[1]) != 2)
		{
			fprintf(stderr, "ERROR: dup failed\n");
			exit(1);
		}
		close(pipefd[1]);

		libmail_changeuidgid(MAILUID, MAILGID);

		fn=qmsgsdatname(p->inum);

		if (faxconvert(fn, faxopts, &n_cover_pages))
			exit (1);

		if ((fp=fopen(FAXTMPDIR "/.ncoverpages", "w")) == NULL ||
		    fprintf(fp, "%d\n", n_cover_pages) < 0 ||
		    fflush(fp) < 0)
			exit(1);
		fclose(fp);
		exit(0);
	}

	close(pipefd[1]);

	err_args.ctf= &ctf;
	err_args.nreceip=nrecipient;

	if (read_childerrmsg(child_proc, pipefd[0],
			     &faxconvert_cleanup, &err_args))
	{
		ctlfile_close(&ctf);
		return;
	}

	/* Hit it */

	if ((fp=fopen(FAXTMPDIR "/.ncoverpages", "r")) == NULL ||
	    fscanf(fp, "%d", &n_cover_pages) != 1)
	{
		if (fp)
			fclose(fp);

		ctlfile_append_reply(err_args.ctf,
				     err_args.nreceip,
				     "Internal error: cannot read number of cover pages",
				     COMCTLFILE_DELFAIL, 0);
		ctlfile_close(&ctf);
		exit(0);
	}

	page_list=read_dir_sort_filenames(FAXTMPDIR, FAXTMPDIR "/");

	if (!page_list)
	{
		clog_msg_start_err();
		clog_msg_str("courierfax: INTERNAL ERROR - no pages to xmit.");
		clog_msg_send();
		exit(1);
	}

	/* Keep trying until the modem line is unlocked */

	do
	{
		if (pipe(pipefd) < 0)
		{
			clog_msg_errno();
		}

		child_proc=fork();
		if (child_proc < 0)
		{
			clog_msg_errno();
			return;
		}

		if (child_proc == 0)
		{
			unsigned page_cnt=0;
			char **argvec;

			close(pipefd[0]);
			close(0);
			if (open("/dev/null", O_RDONLY) != 0)
			{
				perror("/dev/null");
				exit(1);
			}
			close(1);
			if (dup(pipefd[1]) != 1)
			{
				perror("dup");
				exit(1);
			}
			close(2);
			if (dup(pipefd[1]) != 2)
			{
				fprintf(stderr, "ERROR: dup failed\n");
				exit(1);
			}
			close(pipefd[1]);

			for (pp=page_list; pp; pp=pp->next)
				++page_cnt;

#if 0
			while (page_list)
			{
				unlink(page_list->filename);
				page_list=page_list->next;
			}

			exit(0);
#endif

			argvec=(char **)courier_malloc(sizeof(char *)*
						       (page_cnt+10));

			argvec[0]=SENDFAX;
			argvec[1]="-v";
			argvec[2]="-r";

			page_cnt=3;

			if (faxopts & FAX_LOWRES)
				argvec[page_cnt++]="-n";

			argvec[page_cnt++]=(char *)receipient;

			while (page_list)
			{
				argvec[page_cnt++]=page_list->filename;
				page_list=page_list->next;
			}
			argvec[page_cnt]=0;
			execv(SENDFAX, argvec);
			perror(SENDFAX);
			exit(1);
		}
		close(pipefd[1]);

		err_args.ctf= &ctf;
		err_args.nreceip=nrecipient;
		err_args.file_list=page_list;
		err_args.is_locked=0;
		err_args.n_cover_pages=n_cover_pages;

		if (read_childerrmsg(child_proc, pipefd[0],
				     &faxsend_cleanup, &err_args) == 0)
		{
			size_t npages=0;
			char fmtbuf[NUMBUFSIZE];
			char fmtbuf1[NUMBUFSIZE];
			char fmtbuf2[NUMBUFSIZE+100];

			for (pp=page_list; pp; pp=pp->next)
				++npages;

			libmail_str_size_t(npages, fmtbuf);
			libmail_str_size_t(n_cover_pages, fmtbuf1);

			sprintf(fmtbuf2,
				"%s pages - including %s cover page(s)"
				" - sent by fax.", fmtbuf, fmtbuf1);

			ctlfile_append_reply(&ctf, (unsigned)
					     nrecipient,
					     fmtbuf2,
					     COMCTLFILE_DELSUCCESS, " l");
			break;
		}
	} while (err_args.is_locked);

	ctlfile_close(&ctf);
	rmdir_contents(FAXTMPDIR);
}
Example #25
0
static int docommand(const char *extension, const char *sender,
		const char *receipient, const char *defaultext,
		FILE *f, const char *username, const char *userhome,
		const char *command,
		const char *dtline,
		const char *rpline,
		const char *ufromline,
		const char *quota,
		const char *defaultmail,
		int recursion_level)
{
char	*envs[19];
const char *p;
const char *hostp;
pid_t	pid;
int	i;
int	wait_stat;
int	pipefd[2];
int	isrecursive=0;
char	*newcommand=0;
const char *maildropdefault=getenv("MAILDROPDEFAULT");
const char *shell=getenv("SHELL");

	if (!maildropdefault)
		maildropdefault="./Maildir";
	if (!shell)
		shell="/bin/sh";

	envs[0]=courier_malloc(strlen(userhome)+sizeof("HOME="));
	strcat(strcpy(envs[0], "HOME="), userhome);
	envs[1]=courier_malloc(strlen(username)+sizeof("USER="******"USER="******"SENDER="));
	strcat(strcpy(envs[2], "SENDER="), sender);
	envs[3]=courier_malloc(strlen(receipient)+sizeof("RECIPIENT="));
	strcat(strcpy(envs[3], "RECIPIENT="), receipient);

	p=strrchr(receipient, '@');
	if (p)	hostp=p+1;
	else
	{
		hostp="localhost";
		p=receipient+strlen(receipient);
	}

	envs[4]=courier_malloc(strlen(hostp)+sizeof("HOST="));
	strcat(strcpy(envs[4], "HOST="), hostp);
	envs[5]=courier_malloc(p-receipient + sizeof("LOCAL="));
	strcpy(envs[5], "LOCAL=");
	memcpy(envs[5]+6, receipient,  p-receipient);
	envs[5][6+(p-receipient)]=0;

	envs[6]=courier_malloc(strlen(extension)+sizeof("EXT="));
	strcat(strcpy(envs[6], "EXT="), extension);

	p=strchr(extension, '-');
	if (p)	p++;

	envs[7]=courier_malloc((p ? strlen(p):0)+sizeof("EXT2="));
	strcat(strcpy(envs[7], "EXT2="), p ? p:"");

	if (p)
		p=strchr(p, '-');
	if (p)	p++;

	envs[8]=courier_malloc((p ? strlen(p):0)+sizeof("EXT3="));
	strcat(strcpy(envs[8], "EXT3="), p ? p:"");

	if (p)
		p=strchr(p, '-');
	if (p)	p++;

	envs[9]=courier_malloc((p ? strlen(p):0)+sizeof("EXT4="));
	strcat(strcpy(envs[9], "EXT4="), p ? p:"");

	envs[10]=courier_malloc((defaultext ? strlen(defaultext):0)+sizeof("DEFAULT="));
	strcat(strcpy(envs[10], "DEFAULT="), defaultext ? defaultext:"");

	envs[11]=courier_malloc(strlen(dtline)+sizeof("DTLINE="));
	strcat(strcpy(envs[11], "DTLINE="), dtline);

	envs[12]=courier_malloc(strlen(rpline)+sizeof("RPLINE="));
	strcat(strcpy(envs[12], "RPLINE="), rpline);

	envs[13]=courier_malloc(strlen(ufromline)+sizeof("UFLINE="));
	strcat(strcpy(envs[13], "UFLINE="), ufromline);

	p=getenv("PATH");
	if (!p)	p="/bin:/usr/bin:/usr/local/bin";

	envs[14]=courier_malloc(strlen(p)+sizeof("PATH="));
	strcat(strcpy(envs[14], "PATH="), p);

	envs[15]=courier_malloc(strlen(quota)+sizeof("MAILDIRQUOTA="));
	strcat(strcpy(envs[15], "MAILDIRQUOTA="), quota);

	envs[16]=courier_malloc(strlen(maildropdefault)
				+sizeof("MAILDROPDEFAULT="));
	strcat(strcpy(envs[16], "MAILDROPDEFAULT="), maildropdefault);

	envs[17]=courier_malloc(strlen(shell)
				+sizeof("SHELL="));
	strcat(strcpy(envs[17], "SHELL="), shell);
	envs[18]=0;

	if (*command == '|')
	{
		isrecursive=1;
		++command;
		while (*command == ' ' || *command == '\t')
			++command;
		if (pipe(pipefd) < 0)
		{
			clog_msg_prerrno();
			exit(EX_TEMPFAIL);
		}
	}

	if ((pid=fork()) < 0)
	{
		clog_msg_prerrno();
		exit(EX_TEMPFAIL);
	}

	if (pid == 0)
	{
	const char *args[8];

		/*
		** External commands have stdout redirected to stderr,
		** and stdin set to the message.
		*/
		dup2(2, 1);
		if (fileno(f) != 0)
		{
			dup2(fileno(f), 0);
			fclose(f);
		}

		if (isrecursive)
		{
		const char *c;

			dup2(pipefd[1], 1);
			close(pipefd[0]);
			close(pipefd[1]);
			if (recursion_level >= 3)
			{
				fprintf(stderr, "Maximum recursion level for dynamic delivery instructions exceeded.\n");
				fflush(stderr);
				_exit(EX_NOUSER);
			}

			if ((c=getenv("DYNAMICDELIVERIES")) != 0 &&
				atoi(c) == 0)
			{
				fprintf(stderr, "Dynamic delivery instructions disabled by administrator.\n");
				fflush(stderr);
				_exit(EX_NOUSER);
			}
		}

		if ((p=config_maildropmda()) != 0 && *p &&
			strcmp(p, command) == 0)
		{
			/* Special magic for maildrop */

			args[0]="maildrop";
			args[1]="-A";
			args[2]=dtline;
			args[3]="-A";
			args[4]=rpline;
			args[5]="-f";
			args[6]=sender;
			args[7]=0;
		}
		else
		{
			p=getenv("SHELL");
			if (!p || !*p)	p="/bin/sh";

			args[0]=p;
			args[1]="-c";
			args[2]=command;
			args[3]=0;
		}
		lseek(0, 0L, SEEK_SET);

		for (i=0; envs[i]; ++i)
			putenv(envs[i]);

		execv(p, (char **)args);
		fprintf(stderr, "Cannot run %s\n", p);
		_exit(EX_TEMPFAIL);
	}
	for (i=0; envs[i]; i++)
		free(envs[i]);

	if (isrecursive)
	{
		close(pipefd[1]);
		newcommand=read_command(pipefd[0]);
		close(pipefd[0]);
	}

	while (wait(&wait_stat) != pid)
		;

	if (WIFEXITED(wait_stat))
	{
	int	rc=WEXITSTATUS(wait_stat);

		if (rc == 0 || rc == 99)
		{
			if (isrecursive)
				dodel(username, userhome, f, newcommand,
					extension, sender, receipient,
					defaultext, quota, defaultmail,
					recursion_level+1);
		}
		if (newcommand)	free(newcommand);

		return (rc);
	}
	if (newcommand)	free(newcommand);

	return (EX_NOPERM);
}
Example #26
0
void drvinfo::init()
{
unsigned	cnt, i;
struct	rw_transport *p;

	module_dsn=0;
	queuelo=0;
	for (cnt=0, p=rw_transport_first; p; p=p->next)
		++cnt;
	if ((modules=new drvinfo[cnt]) == 0)	clog_msg_errno();
	cnt=0;

	for (p=rw_transport_first; p; p=p->next)
	{
	char	*namebuf=(char *)courier_malloc(
		sizeof( SYSCONFDIR "/module.")+strlen(p->name));

		strcat(strcpy(namebuf, SYSCONFDIR "/module."),
				p->name);

	FILE	*config=fopen(namebuf, "r");

		if (!config)
		{
			clog_msg_start_err();
			clog_msg_str("Cannot open ");
			clog_msg_str(namebuf);
			clog_msg_send();
			exit(1);
		}
		free(namebuf);
		
	unsigned maxdels=1;
	unsigned maxhost=1;
	unsigned maxrcpt=1;
	char	*prog=0;
	char	buf[BUFSIZ];

		while (fgets(buf, sizeof(buf), config) != 0)
		{
		char	*p;

			if ((p=strchr(buf, '#')) != 0)	*p=0;
			p=strtok(buf, " \t\r\n=");
			if (strcmp(p, "MAXDELS") == 0)
			{
				p=strtok(NULL, " \t\r\n=");
				if (p)	maxdels=atoi(p);
			}
			else if (strcmp(p, "MAXHOST") == 0)
			{
				p=strtok(NULL, " \t\r\n=");
				if (p)	maxhost=atoi(p);
			}
			else if (strcmp(p, "MAXRCPT") == 0)
			{
				p=strtok(NULL, " \t\r\n=");
				if (p)	maxrcpt=atoi(p);
			}
			else if (strcmp(p, "PROG") == 0 && !prog)
			{
				p=strtok(NULL, "\t\r\n=");
				if (p)
				{
					prog=(char *)
						courier_malloc(strlen(p)+1);
					strcpy(prog, p);
				}
			}
		}
		fclose(config);
		if (!prog)	continue;	// Input only module

		modules[cnt].module=p;
		p->udata=(void *)&modules[cnt];
		modules[cnt].delinfo_list.resize(maxdels);
		modules[cnt].hosts_list.resize(maxdels);
		queuelo += maxdels;
		modules[cnt].maxhost=maxhost;
		modules[cnt].maxrcpt=maxrcpt;
		modules[cnt].delpfreefirst=0;

		if (strcmp(p->name, DSN) == 0)
			module_dsn= &modules[cnt];

		for (i=0; i<maxdels; i++)
		{
			modules[cnt].delinfo_list[i].delid=i;
			modules[cnt].delinfo_list[i].freenext=
				modules[cnt].delpfreefirst;
			modules[cnt].delpfreefirst=
				&modules[cnt].delinfo_list[i];
		}

		modules[cnt].hdlvrpfree=0;
		for (i=0; i<maxdels; i++)
		{
			modules[cnt].hosts_list[i].next=
				modules[cnt].hdlvrpfree;
			modules[cnt].hdlvrpfree=&modules[cnt].hosts_list[i];
		}
		modules[cnt].hdlvrpfirst=0;
		modules[cnt].hdlvrplast=0;

	int	pipe0[2], pipe1[2];

		if (pipe(pipe0) || pipe(pipe1))
			clog_msg_errno();

		switch (modules[cnt].module_pid=fork())	{
		case 0:
#if 0
// replaced by close-on-exec, below

			for (i=cnt; i; )
			{
				--i;
				fclose(modules[i].module_to);
				close(modules[i].module_from.fd);
			}
#endif
			close(pipe0[1]);
			close(pipe1[0]);
			dup2(pipe0[0], 0);
			dup2(pipe1[1], 1);
			close(pipe0[0]);
			close(pipe1[1]);
			signal(SIGCHLD, SIG_DFL);

			if (chdir(MODULEDIR) ||
				chdir(modules[cnt].module->name))
			{
				clog_msg_start_err();
				clog_msg_str(MODULEDIR "/");
				clog_msg_str(modules[cnt].module->name);
				clog_msg_str(" does not exist.");
				clog_msg_send();
				clog_msg_errno();
			}

			{
			char maxdels_buf[MAXLONGSIZE+15];
			char maxhost_buf[MAXLONGSIZE+15];
			char maxrcpt_buf[MAXLONGSIZE+15];
			const char *sh=getenv("SHELL");

				sprintf(maxdels_buf, "MAXDELS=%ld",
					(long)maxdels);
				sprintf(maxhost_buf, "MAXHOST=%ld",
					(long)maxhost);
				sprintf(maxrcpt_buf, "MAXRCPT=%ld",
					(long)maxrcpt);

				putenv(maxdels_buf);
				putenv(maxhost_buf);
				putenv(maxrcpt_buf);

			const char *ch=courierdir();
			char	*p=(char *)courier_malloc(strlen(ch)+
					sizeof("COURIER_HOME="));

				strcat(strcpy(p,"COURIER_HOME="), ch);
				putenv(p);

				if (!sh)	sh="/bin/sh";
				execl(sh, sh, "-c", prog, (char *)0);
				clog_msg_start_err();
				clog_msg_str(MODULEDIR "/");
				clog_msg_str(modules[cnt].module->name);
				clog_msg_str(": ");
				clog_msg_str(prog);
				clog_msg_send();
				clog_msg_errno();
			}
		case -1:
			clog_msg_errno();
			break;
		}

		close(pipe0[0]);
		close(pipe1[1]);

		if (fcntl(pipe0[1], F_SETFD, FD_CLOEXEC) ||
			fcntl(pipe1[0], F_SETFD, FD_CLOEXEC))
			clog_msg_errno();

		if ((modules[cnt].module_to=fdopen(pipe0[1], "w")) == NULL)
			clog_msg_errno();

		mybuf_init( &modules[cnt].module_from, pipe1[0] );

		clog_msg_start_info();
		clog_msg_str("Started ");
		clog_msg_str(prog);
		clog_msg_str(", pid=");
		clog_msg_int(modules[cnt].module_pid);
		clog_msg_str(", maxdels=");
		clog_msg_int(maxdels);
		clog_msg_str(", maxhost=");
		clog_msg_int(maxhost);
		clog_msg_str(", maxrcpt=");
		clog_msg_int(maxrcpt);
		clog_msg_send();
		free(prog);
		cnt++;
	}
	nmodules=cnt;

	if (queuelo < 200)	queuelo=200;

char	*cfname=config_localfilename("queuelo");
char	*conf=config_read1l(cfname);

	if (conf)
	{
		queuelo=atoi(conf);
		free(conf);
	}
	free(cfname);
	if (queuelo < 20)	queuelo=20;

	cfname=config_localfilename("queuehi");
	conf=config_read1l(cfname);
	if (conf)
	{
		queuehi=atoi(conf);
		free(conf);
	}
	else
		queuehi=queuelo < 500 ? queuelo * 2:queuelo+1000;
	if (queuehi < queuelo)	queuehi=queuelo;
	free(cfname);

	clog_msg_start_info();
	clog_msg_str("queuelo=");
	clog_msg_int(queuelo);
	clog_msg_str(", queuehi=");
	clog_msg_int(queuehi);
	clog_msg_send();

	if (module_dsn == 0)
	{
		clog_msg_start_err();
		clog_msg_str("Driver dsn not found.");
		clog_msg_send();
		exit(1);
	}
}
Example #27
0
static void esmtpparent()
{
unsigned i;
fd_set	fdc, fds;
time_t	current_time;

	libmail_changeuidgid(MAILUID, MAILGID);
	module_init(&terminated_child);

	if ((info=(struct esmtpchildinfo *)malloc(sizeof(*info)*
		module_nchildren)) == 0)
		clog_msg_errno();
	for (i=0; i<module_nchildren; i++)
	{
		info[i].pid= -1;
		info[i].cmdpipe= -1;
		info[i].host=0;
		info[i].pendel=0;
	}
	if (pipe(completionpipe) < 0)
		clog_msg_errno();

	if ((childresultpipe=fdopen(completionpipe[0], "r")) == 0)
		clog_msg_errno();
	FD_ZERO(&fdc);
	FD_SET(0, &fdc);
	FD_SET(completionpipe[0], &fdc);
	mybuf_init(&courierdbuf, 0);
	mybuf_init(&childbuf, completionpipe[0]);

	module_blockset();
	time(&current_time);

	for (;;)
	{
	time_t	wait_time;
	struct	timeval	tv;

		wait_time=0;
		for (i=0; i<module_nchildren; i++)
		{
			if (!ESMTP_IDLE(&info[i]))	continue;
			if (info[i].termtime <= current_time)
			{
				close(info[i].cmdpipe);
				info[i].cmdpipe= -1;
				continue;
			}

			if (wait_time == 0 || info[i].termtime < wait_time)
				wait_time=info[i].termtime;
		}

		if (wait_time)
		{
			tv.tv_sec= wait_time - current_time;
			tv.tv_usec=0;
		}

		fds=fdc;

		module_blockclr();
                while (select(completionpipe[0]+1, &fds, (fd_set *)0, (fd_set *)0,
                                (wait_time ? &tv:(struct timeval *)0)) < 0)
                {
                        if (errno != EINTR)     clog_msg_errno();
                }

		module_blockset();
		time(&current_time);

		if (FD_ISSET(completionpipe[0], &fds))
		{
		char	*line;

			do
			{
			pid_t	p;

				line=module_getline( &call_mybuf_get,
						&childbuf);

				if (parse_ack(line, &i, &p) ||
					i >= module_nchildren ||
					(p == info[i].pid &&
						!ESMTP_BUSY(&info[i])))
				{
					clog_msg_start_err();
					clog_msg_str("INVALID message from child process.");
					clog_msg_send();
					_exit(0);
				}
				if (p != info[i].pid)	continue;
				info[i].isbusy=0;
				info[i].termtime=current_time + esmtpkeepalive;
				if (info[i].pendel)
				{
					free(info[i].pendel);
					info[i].pendel=0;
				}

				module_completed(i, module_delids[i]);
			} while (mybuf_more(&childbuf));
		}

		if (!FD_ISSET(0, &fds))	continue;

		do
		{
		char	**cols;
		const char *hostp;
		size_t	hostplen;
		time_t	misctime;
		unsigned j;
		char	*line;

			line=module_getline( &call_mybuf_get, &courierdbuf);
			if (!line)
			{
				module_restore();

				/*
				** If all processes are idle, wait for them
				** to finish normally.  Otherwise, kill
				** the processes.
				*/

				for (j=0; j<module_nchildren; j++)
					if (ESMTP_BUSY(&info[j]))
						break;

				if (j < module_nchildren)
				{
					for (j=0; j<module_nchildren; j++)
						if (info[j].pid > 0)
							kill(info[j].pid,
								SIGTERM);
				}
				else
				{
				int	waitstat;

					for (j=0; j<module_nchildren; j++)
					{
						if (info[j].cmdpipe > 0)
						{
							close(info[j].cmdpipe);
							info[j].cmdpipe= -1;
						}
					}
					while (wait(&waitstat) != -1 ||
						errno == EINTR)
						;
				}
				_exit(0);
			}

			cols=module_parsecols(line);

			if (!cols)	_exit(0);

			hostp=MODULEDEL_HOST(cols);
			for (hostplen=0; hostp[hostplen] &&
				hostp[hostplen] != '\t'; hostplen++)
				;

			for (i=0; i<module_nchildren; i++)
			{
				if (!ESMTP_IDLE(&info[i])) continue;
				if (memcmp(info[i].host, hostp, hostplen) == 0
					&& info[i].host[hostplen] == 0)
					break;
			}

			if (i < module_nchildren)	/* Reuse a process */
			{
				send_child(i, line, cols);
				continue;
			}

			for (i=0; i<module_nchildren; i++)
				if (ESMTP_NOCHILD(&info[i]))	break;

			if (i < module_nchildren)	/* We can fork */
			{
				start_child(i, line, cols);
				send_child(i, line, cols);
				continue;
			}

			/*
			** Find a process that's been idled the longest,
			** and reuse that one.
			*/

			misctime=0;
			j=0;
			for (i=0; i<module_nchildren; i++)
			{
				if (ESMTP_IDLE(&info[i]) &&
					(misctime == 0 || misctime >
						info[i].termtime))
				{
					j=i;
					misctime=info[i].termtime;
				}
			}
			if (misctime)
			{
				if (info[j].pendel)
				{
					clog_msg_start_err();
					clog_msg_str("INTERNAL ERROR: unexpected scheduled delivery.");
					clog_msg_send();
					_exit(1);
				}

				info[j].pendel=strcpy(
					courier_malloc(strlen(line)+1),
					line);
				close(info[j].cmdpipe);
				info[j].cmdpipe= -1;
				continue;
			}

			/* The ONLY remaining possibility is something in
			** the TERMINATING stage, without another delivery
			** already scheduled for that slot.
			*/

			for (i=0; i<module_nchildren; i++)
			{
				if (ESMTP_TERMINATING(&info[i]) &&
					info[i].pendel == 0)
					break;
			}

			if (i < module_nchildren)
			{
				info[i].pendel=strcpy(
					courier_malloc(strlen(line)+1),
					line);
				continue;
			}

			clog_msg_start_err();
			clog_msg_str("INTERNAL ERROR: unexpected delivery.");
			clog_msg_send();
			_exit(1);
		} while (mybuf_more(&courierdbuf));
	}
}