LDADD= -lssl -lcrypto
PROG= dma
-SRCS= base64.c conf.c crypto.c net.c dma.c aliases_scan.l aliases_parse.y spool.c local.c
+SRCS= base64.c conf.c crypto.c net.c dma.c aliases_scan.l aliases_parse.y spool.c local.c util.c
MAN= dma.8
BINOWN= root
/*
* Add entry to the SMTP auth user list
*/
-static void
+static int
add_smtp_auth_user(char *userstring, char *password)
{
struct authuser *a;
temp = strrchr(userstring, '|');
if (temp == NULL)
- errx(1, "auth.conf file in wrong format");
- /* XXX don't use errx */
+ return (-1);
a->host = strdup(temp+1);
a->login = strdup(strtok(userstring, "|"));
if (a->login == NULL)
- errx(1, "auth.conf file in wrong format");
+ return (-1);
SLIST_INSERT_HEAD(&authusers, a, next);
+
+ return (0);
}
/*
if ((word = strtok(line, DP)) != NULL) {
data = strtok(NULL, DP);
if (data != NULL) {
- add_smtp_auth_user(word, data);
+ if (add_smtp_auth_user(word, data) < 0)
+ return (-1);
}
}
}
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
-#include <netdb.h>
#include <paths.h>
#include <pwd.h>
#include <signal.h>
struct authusers authusers = LIST_HEAD_INITIALIZER(authusers);
struct config *config;
const char *username;
+const char *logident_base;
static int daemonize = 1;
-static const char *logident_base;
-
-const char *
-hostname(void)
-{
- static char name[MAXHOSTNAMELEN+1];
- int initialized = 0;
- FILE *fp;
- size_t len;
-
- if (initialized)
- return (name);
-
- if (config->mailname != NULL && config->mailname[0] != '\0') {
- snprintf(name, sizeof(name), "%s", config->mailname);
- initialized = 1;
- return (name);
- }
- if (config->mailnamefile != NULL && config->mailnamefile[0] != '\0') {
- fp = fopen(config->mailnamefile, "r");
- if (fp != NULL) {
- if (fgets(name, sizeof(name), fp) != NULL) {
- len = strlen(name);
- while (len > 0 &&
- (name[len - 1] == '\r' ||
- name[len - 1] == '\n'))
- name[--len] = '\0';
- if (name[0] != '\0') {
- initialized = 1;
- return (name);
- }
- }
- fclose(fp);
- }
- }
- if (gethostname(name, sizeof(name)) != 0)
- strcpy(name, "(unknown hostname)");
- initialized = 1;
- return name;
-}
-
-static void
-setlogident(const char *fmt, ...)
-{
- char *tag = NULL;
-
- if (fmt != NULL) {
- va_list ap;
- char *sufx;
-
- va_start(ap, fmt);
- vasprintf(&sufx, fmt, ap);
- if (sufx != NULL) {
- asprintf(&tag, "%s[%s]", logident_base, sufx);
- free(sufx);
- }
- va_end(ap);
- }
- closelog();
- openlog(tag != NULL ? tag : logident_base, 0, LOG_MAIL);
-}
-
-static const char *
-check_username(const char *name, uid_t ckuid)
-{
- struct passwd *pwd;
-
- if (name == NULL)
- return (NULL);
- pwd = getpwnam(name);
- if (pwd == NULL || pwd->pw_uid != ckuid)
- return (NULL);
- return (name);
-}
-
-static void
-set_username(void)
-{
- struct passwd *pwd;
- char *u = NULL;
- uid_t uid;
-
- uid = getuid();
- username = check_username(getlogin(), uid);
- if (username != NULL)
- return;
- username = check_username(getenv("LOGNAME"), uid);
- if (username != NULL)
- return;
- username = check_username(getenv("USER"), uid);
- if (username != NULL)
- return;
- pwd = getpwuid(uid);
- if (pwd != NULL && pwd->pw_name != NULL && pwd->pw_name[0] != '\0' &&
- (u = strdup(pwd->pw_name)) != NULL) {
- username = check_username(u, uid);
- if (username != NULL)
- return;
- else
- free(u);
- }
- asprintf(__DECONST(void *, &username), "%ld", (long)uid);
- if (username != NULL)
- return;
- username = "unknown-or-invalid-username";
-}
static char *
set_from(const char *osender)
return (-1);
}
-static void
-deltmp(void)
-{
- struct stritem *t;
-
- SLIST_FOREACH(t, &tmpfs, next) {
- unlink(t->str);
- }
-}
-
-int
-open_locked(const char *fname, int flags, ...)
-{
- int mode = 0;
-
- if (flags & O_CREAT) {
- va_list ap;
- va_start(ap, flags);
- mode = va_arg(ap, int);
- va_end(ap);
- }
-
-#ifndef O_EXLOCK
- int fd, save_errno;
-
- fd = open(fname, flags, mode);
- if (fd < 0)
- return(fd);
- if (flock(fd, LOCK_EX|((flags & O_NONBLOCK)? LOCK_NB: 0)) < 0) {
- save_errno = errno;
- close(fd);
- errno = save_errno;
- return(-1);
- }
- return(fd);
-#else
- return(open(fname, flags|O_EXLOCK, mode));
-#endif
-}
-
-static char *
-rfc822date(void)
-{
- static char str[50];
- size_t error;
- time_t now;
-
- now = time(NULL);
- error = strftime(str, sizeof(str), "%a, %d %b %Y %T %z",
- localtime(&now));
- if (error == 0)
- strcpy(str, "(date fail)");
- return (str);
-}
-
-static int
-strprefixcmp(const char *str, const char *prefix)
-{
- return (strncasecmp(str, prefix, strlen(prefix)));
-}
-
static int
readmail(struct queue *queue, const char *sender, int nodot)
{
config = calloc(1, sizeof(*config));
if (config == NULL)
- err(1, NULL);
+ errlog(1, NULL);
if (parse_conf(CONF_PATH) < 0) {
free(config);
- err(1, "can not read config file");
+ errlog(1, "can not read config file");
}
if (config->features & VIRTUAL)
if (parse_virtuser(config->virtualpath) < 0)
- err(1, "can not read virtual user file `%s'",
+ errlog(1, "can not read virtual user file `%s'",
config->virtualpath);
if (parse_authfile(config->authpath) < 0)
- err(1, "can not read SMTP authentication file");
+ errlog(1, "can not read SMTP authentication file");
if (showq) {
- load_queue(&lqueue);
+ if (load_queue(&lqueue) < 0)
+ errlog(1, "can not load queue");
show_queue(&lqueue);
return (0);
}
if (doqueue) {
- load_queue(&lqueue);
+ if (load_queue(&lqueue) < 0)
+ errlog(1, "can not load queue");
run_queue(&lqueue);
return (0);
}
if (read_aliases() != 0)
- err(1, "can not read aliases file `%s'", config->aliases);
+ errlog(1, "can not read aliases file `%s'", config->aliases);
if ((sender = set_from(sender)) == NULL)
- err(1, NULL);
+ errlog(1, NULL);
for (i = 0; i < argc; i++) {
if (add_recp(&queue, argv[i], sender, 1) != 0)
- errx(1, "invalid recipient `%s'", argv[i]);
+ errlogx(1, "invalid recipient `%s'", argv[i]);
}
if (LIST_EMPTY(&queue.queue))
- errx(1, "no recipients");
+ errlogx(1, "no recipients");
if (newspoolf(&queue, sender) != 0)
- err(1, "can not create temp file");
+ errlog(1, "can not create temp file");
setlogident("%s", queue.id);
if (readmail(&queue, sender, nodot) != 0)
- err(1, "can not read mail");
+ errlog(1, "can not read mail");
if (linkspool(&queue, sender) != 0)
- err(1, "can not create spools");
+ errlog(1, "can not create spools");
/* From here on the mail is safe. */
extern struct virtusers virtusers;
extern struct authusers authusers;
extern const char *username;
+extern const char *logident_base;
extern char neterr[BUF_SIZE];
int base64_decode(const char *, void *);
/* dma.c */
-int open_locked(const char *, int, ...);
int add_recp(struct queue *, const char *, const char *, int);
-const char *hostname(void);
/* spool.c */
int newspoolf(struct queue *, const char *);
int linkspool(struct queue *, const char *);
-void load_queue(struct queue *);
+int load_queue(struct queue *);
void delqueue(struct qitem *);
int aquirespool(struct qitem *);
void dropspool(struct queue *, struct qitem *);
/* local.c */
int deliver_local(struct qitem *, const char **errmsg);
+
+/* util.c */
+const char *hostname(void);
+void setlogident(const char *, ...);
+void errlog(int, const char *, ...);
+void errlogx(int, const char *, ...);
+void set_username(void);
+void deltmp(void);
+int open_locked(const char *, int, ...);
+char *rfc822date(void);
+int strprefixcmp(const char *, const char *);
+
#endif
delfiles:
LIST_FOREACH(it, &queue->queue, next) {
- unlink(it->queuefn);
unlink(it->mailfn);
+ unlink(it->queuefn);
}
return (-1);
}
-void
+int
load_queue(struct queue *queue)
{
struct qitem *it;
continue;
skip_item:
- warn("reading queue: `%s'", queuefn);
+ syslog(LOG_INFO, "could not pick up queue file: `%s'/`%s': %m", queuefn, mailfn);
if (sender != NULL)
free(sender);
if (queuefn != NULL)
fclose(mailf);
}
closedir(spooldir);
- return;
+ return (0);
fail:
- err(1, "reading queue");
+ return (-1);
}
void
delqueue(struct qitem *it)
{
- unlink(it->queuefn);
unlink(it->mailfn);
+ unlink(it->queuefn);
if (it->queuef != NULL)
fclose(it->queuef);
if (it->mailf != NULL)
if (it->queuef == NULL) {
queuefd = open_locked(it->queuefn, O_RDWR);
if (queuefd < 0)
- return (-1);
+ goto fail;
it->queuef = fdopen(queuefd, "r+");
if (it->queuef == NULL)
- return (-1);
+ goto fail;
}
if (it->mailf == NULL) {
it->mailf = fopen(it->mailfn, "r");
if (it->mailf == NULL)
- return (-1);
+ goto fail;
}
return (0);
+
+fail:
+ syslog(LOG_INFO, "could not aquire queue file: %m");
+ return (-1);
}
void
--- /dev/null
+/*
+ * Copyright (c) 2008 The DragonFly Project. All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Simon 'corecode' Schubert <corecode@fs.ei.tum.de>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "dma.h"
+
+const char *
+hostname(void)
+{
+ static char name[MAXHOSTNAMELEN+1];
+ int initialized = 0;
+ FILE *fp;
+ size_t len;
+
+ if (initialized)
+ return (name);
+
+ if (config->mailname != NULL && config->mailname[0] != '\0') {
+ snprintf(name, sizeof(name), "%s", config->mailname);
+ initialized = 1;
+ return (name);
+ }
+ if (config->mailnamefile != NULL && config->mailnamefile[0] != '\0') {
+ fp = fopen(config->mailnamefile, "r");
+ if (fp != NULL) {
+ if (fgets(name, sizeof(name), fp) != NULL) {
+ len = strlen(name);
+ while (len > 0 &&
+ (name[len - 1] == '\r' ||
+ name[len - 1] == '\n'))
+ name[--len] = '\0';
+ if (name[0] != '\0') {
+ initialized = 1;
+ return (name);
+ }
+ }
+ fclose(fp);
+ }
+ }
+ if (gethostname(name, sizeof(name)) != 0)
+ strcpy(name, "(unknown hostname)");
+ initialized = 1;
+ return name;
+}
+
+void
+setlogident(const char *fmt, ...)
+{
+ char *tag = NULL;
+
+ if (fmt != NULL) {
+ va_list ap;
+ char *sufx;
+
+ va_start(ap, fmt);
+ vasprintf(&sufx, fmt, ap);
+ if (sufx != NULL) {
+ asprintf(&tag, "%s[%s]", logident_base, sufx);
+ free(sufx);
+ }
+ va_end(ap);
+ }
+ closelog();
+ openlog(tag != NULL ? tag : logident_base, 0, LOG_MAIL);
+}
+
+void
+errlog(int exitcode, const char *fmt, ...)
+{
+ int oerrno = errno;
+ va_list ap;
+ char *outs = NULL;
+
+ if (fmt != NULL) {
+ va_start(ap, fmt);
+ vasprintf(&outs, fmt, ap);
+ va_end(ap);
+ }
+
+ if (outs != NULL) {
+ syslog(LOG_ERR, "%s: %m", outs);
+ fprintf(stderr, "%s: %s: %s\n", getprogname(), outs, strerror(oerrno));
+ } else {
+ syslog(LOG_ERR, "%m");
+ fprintf(stderr, "%s: %s\n", getprogname(), strerror(oerrno));
+ }
+
+ exit(exitcode);
+}
+
+void
+errlogx(int exitcode, const char *fmt, ...)
+{
+ va_list ap;
+ char *outs = NULL;
+
+ if (fmt != NULL) {
+ va_start(ap, fmt);
+ vasprintf(&outs, fmt, ap);
+ va_end(ap);
+ }
+
+ if (outs != NULL) {
+ syslog(LOG_ERR, "%s", outs);
+ fprintf(stderr, "%s: %s\n", getprogname(), outs);
+ } else {
+ syslog(LOG_ERR, "Unknown error");
+ fprintf(stderr, "%s: Unknown error\n", getprogname());
+ }
+
+ exit(exitcode);
+}
+
+static const char *
+check_username(const char *name, uid_t ckuid)
+{
+ struct passwd *pwd;
+
+ if (name == NULL)
+ return (NULL);
+ pwd = getpwnam(name);
+ if (pwd == NULL || pwd->pw_uid != ckuid)
+ return (NULL);
+ return (name);
+}
+
+void
+set_username(void)
+{
+ struct passwd *pwd;
+ char *u = NULL;
+ uid_t uid;
+
+ uid = getuid();
+ username = check_username(getlogin(), uid);
+ if (username != NULL)
+ return;
+ username = check_username(getenv("LOGNAME"), uid);
+ if (username != NULL)
+ return;
+ username = check_username(getenv("USER"), uid);
+ if (username != NULL)
+ return;
+ pwd = getpwuid(uid);
+ if (pwd != NULL && pwd->pw_name != NULL && pwd->pw_name[0] != '\0' &&
+ (u = strdup(pwd->pw_name)) != NULL) {
+ username = check_username(u, uid);
+ if (username != NULL)
+ return;
+ else
+ free(u);
+ }
+ asprintf(__DECONST(void *, &username), "%ld", (long)uid);
+ if (username != NULL)
+ return;
+ username = "unknown-or-invalid-username";
+}
+
+void
+deltmp(void)
+{
+ struct stritem *t;
+
+ SLIST_FOREACH(t, &tmpfs, next) {
+ unlink(t->str);
+ }
+}
+
+int
+open_locked(const char *fname, int flags, ...)
+{
+ int mode = 0;
+
+ if (flags & O_CREAT) {
+ va_list ap;
+ va_start(ap, flags);
+ mode = va_arg(ap, int);
+ va_end(ap);
+ }
+
+#ifndef O_EXLOCK
+ int fd, save_errno;
+
+ fd = open(fname, flags, mode);
+ if (fd < 0)
+ return(fd);
+ if (flock(fd, LOCK_EX|((flags & O_NONBLOCK)? LOCK_NB: 0)) < 0) {
+ save_errno = errno;
+ close(fd);
+ errno = save_errno;
+ return(-1);
+ }
+ return(fd);
+#else
+ return(open(fname, flags|O_EXLOCK, mode));
+#endif
+}
+
+char *
+rfc822date(void)
+{
+ static char str[50];
+ size_t error;
+ time_t now;
+
+ now = time(NULL);
+ error = strftime(str, sizeof(str), "%a, %d %b %Y %T %z",
+ localtime(&now));
+ if (error == 0)
+ strcpy(str, "(date fail)");
+ return (str);
+}
+
+int
+strprefixcmp(const char *str, const char *prefix)
+{
+ return (strncasecmp(str, prefix, strlen(prefix)));
+}
+