Index: vendor/dma/0.10/LICENSE =================================================================== --- vendor/dma/0.10/LICENSE (nonexistent) +++ vendor/dma/0.10/LICENSE (revision 289122) @@ -0,0 +1,109 @@ +Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>. +Copyright (c) 2008 The DragonFly Project. +All rights reserved. + +This code is derived from software contributed to The DragonFly Project +by Simon Schubert <2@0x2c.org>. + +This code is derived from software contributed to The DragonFly Project +by Matthias Schmidt , University of Marburg, +Germany. + +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. + + +Copyright (c) 1995-2001 Kungliga Tekniska Högskolan +(Royal Institute of Technology, Stockholm, Sweden). +All rights reserved. + +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 Institute 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 INSTITUTE 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 INSTITUTE 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. + + +Copyright (c) 1998 Todd C. Miller + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +Copyright (c) 1998, M. Warner Losh +All rights reserved. + +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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. Index: vendor/dma/0.10/README.markdown =================================================================== --- vendor/dma/0.10/README.markdown (nonexistent) +++ vendor/dma/0.10/README.markdown (revision 289122) @@ -0,0 +1,37 @@ +dma -- DragonFly Mail Agent +=========================== + +dma is a small Mail Transport Agent (MTA), designed for home and +office use. It accepts mails from locally installed Mail User Agents (MUA) +and delivers the mails either locally or to a remote destination. +Remote delivery includes several features like TLS/SSL support and +SMTP authentication. + +dma is not intended as a replacement for real, big MTAs like sendmail(8) +or postfix(1). Consequently, dma does not listen on port 25 for +incoming connections. + + +Building +-------- + +In Linux: + + make + +In BSD: + + cd bsd && make + +Installation +------------ + + make install sendmail-link mailq-link install-spool-dirs install-etc + +See INSTALL for requirements and configuration options. + + +Contact +------- + +Simon Schubert <2@0x2c.org> Index: vendor/dma/0.10/TODO =================================================================== --- vendor/dma/0.10/TODO (nonexistent) +++ vendor/dma/0.10/TODO (revision 289122) @@ -0,0 +1,4 @@ +- unquote/handle quoted local recipients +- handle/use ESMTP extensions +- .forward support +- suggest way to run a queue flush on boot Index: vendor/dma/0.10/VERSION =================================================================== --- vendor/dma/0.10/VERSION (nonexistent) +++ vendor/dma/0.10/VERSION (revision 289122) @@ -0,0 +1 @@ +v0.10 Index: vendor/dma/0.10/aliases_parse.y =================================================================== --- vendor/dma/0.10/aliases_parse.y (nonexistent) +++ vendor/dma/0.10/aliases_parse.y (revision 289122) @@ -0,0 +1,110 @@ +%{ + +#include +#include +#include +#include "dma.h" + +extern int yylineno; +static void yyerror(const char *); + +static void +yyerror(const char *msg) +{ + /** + * Because we do error '\n' below, we need to report the error + * one line above of what yylineno points to. + */ + syslog(LOG_CRIT, "aliases line %d: %s", yylineno - 1, msg); + fprintf(stderr, "aliases line %d: %s\n", yylineno - 1, msg); +} + +int +yywrap(void) +{ + return (1); +} + +%} + +%union { + char *ident; + struct stritem *strit; + struct alias *alias; +} + +%token T_IDENT +%token T_ERROR +%token T_EOF 0 + +%type dests +%type alias aliases + +%% + +start : aliases T_EOF + { + LIST_FIRST(&aliases) = $1; + } + +aliases : /* EMPTY */ + { + $$ = NULL; + } + | alias aliases + { + if ($2 != NULL && $1 != NULL) + LIST_INSERT_AFTER($2, $1, next); + else if ($2 == NULL) + $2 = $1; + $$ = $2; + } + ; + +alias : T_IDENT ':' dests '\n' + { + struct alias *al; + + if ($1 == NULL) + YYABORT; + al = calloc(1, sizeof(*al)); + if (al == NULL) + YYABORT; + al->alias = $1; + SLIST_FIRST(&al->dests) = $3; + $$ = al; + } + | error '\n' + { + YYABORT; + } + ; + +dests : T_IDENT + { + struct stritem *it; + + if ($1 == NULL) + YYABORT; + it = calloc(1, sizeof(*it)); + if (it == NULL) + YYABORT; + it->str = $1; + $$ = it; + } + | T_IDENT ',' dests + { + struct stritem *it; + + if ($1 == NULL) + YYABORT; + it = calloc(1, sizeof(*it)); + if (it == NULL) + YYABORT; + it->str = $1; + SLIST_NEXT(it, next) = $3; + $$ = it; + } + ; + +%% Index: vendor/dma/0.10/aliases_scan.l =================================================================== --- vendor/dma/0.10/aliases_scan.l (nonexistent) +++ vendor/dma/0.10/aliases_scan.l (revision 289122) @@ -0,0 +1,24 @@ +%{ + +#include +#include "dma.h" +#include "aliases_parse.h" + +#define YY_NO_INPUT + +%} + +%option yylineno +%option nounput + +%% + +[^:,#[:space:][:cntrl:]]+ {yylval.ident = strdup(yytext); return T_IDENT;} +^([[:blank:]]*(#.*)?\n)+ ;/* ignore empty lines */ +[:,\n] return yytext[0]; +(\n?[[:blank:]]+|#.*)+ ;/* ignore whitespace and continuation */ +\\\n ;/* ignore continuation. not allowed in comments */ +. return T_ERROR; +<> return T_EOF; + +%% Index: vendor/dma/0.10/conf.c =================================================================== --- vendor/dma/0.10/conf.c (nonexistent) +++ vendor/dma/0.10/conf.c (revision 289122) @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthias Schmidt , University of Marburg, + * Germany. + * + * 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 +#include +#include +#include +#include +#include +#include + +#include "dma.h" + +#define DP ": \t" +#define EQS " \t" + + +/* + * Remove trailing \n's + */ +void +trim_line(char *line) +{ + size_t linelen; + char *p; + + if ((p = strchr(line, '\n'))) + *p = (char)0; + + /* Escape leading dot in every case */ + linelen = strlen(line); + if (line[0] == '.') { + if ((linelen + 2) > 1000) { + syslog(LOG_CRIT, "Cannot escape leading dot. Buffer overflow"); + exit(EX_DATAERR); + } + memmove((line + 1), line, (linelen + 1)); + line[0] = '.'; + } +} + +static void +chomp(char *str) +{ + size_t len = strlen(str); + + if (len == 0) + return; + if (str[len - 1] == '\n') + str[len - 1] = 0; +} + +/* + * Read the SMTP authentication config file + * + * file format is: + * user|host:password + * + * A line starting with # is treated as comment and ignored. + */ +void +parse_authfile(const char *path) +{ + char line[2048]; + struct authuser *au; + FILE *a; + char *data; + int lineno = 0; + + a = fopen(path, "r"); + if (a == NULL) { + errlog(EX_NOINPUT, "can not open auth file `%s'", path); + /* NOTREACHED */ + } + + while (!feof(a)) { + if (fgets(line, sizeof(line), a) == NULL) + break; + lineno++; + + chomp(line); + + /* We hit a comment */ + if (*line == '#') + continue; + /* Ignore empty lines */ + if (*line == 0) + continue; + + au = calloc(1, sizeof(*au)); + if (au == NULL) + errlog(EX_OSERR, NULL); + + data = strdup(line); + au->login = strsep(&data, "|"); + au->host = strsep(&data, DP); + au->password = data; + + if (au->login == NULL || + au->host == NULL || + au->password == NULL) { + errlogx(EX_CONFIG, "syntax error in authfile %s:%d", path, lineno); + /* NOTREACHED */ + } + + SLIST_INSERT_HEAD(&authusers, au, next); + } + + fclose(a); +} + +/* + * XXX TODO + * Check for bad things[TM] + */ +void +parse_conf(const char *config_path) +{ + char *word; + char *data; + FILE *conf; + char line[2048]; + int lineno = 0; + + conf = fopen(config_path, "r"); + if (conf == NULL) { + /* Don't treat a non-existing config file as error */ + if (errno == ENOENT) + return; + errlog(EX_NOINPUT, "can not open config `%s'", config_path); + /* NOTREACHED */ + } + + while (!feof(conf)) { + if (fgets(line, sizeof(line), conf) == NULL) + break; + lineno++; + + chomp(line); + + /* We hit a comment */ + if (strchr(line, '#')) + *strchr(line, '#') = 0; + + data = line; + word = strsep(&data, EQS); + + /* Ignore empty lines */ + if (word == NULL || *word == 0) + continue; + + if (data != NULL && *data != 0) + data = strdup(data); + else + data = NULL; + + if (strcmp(word, "SMARTHOST") == 0 && data != NULL) + config.smarthost = data; + else if (strcmp(word, "PORT") == 0 && data != NULL) + config.port = atoi(data); + else if (strcmp(word, "ALIASES") == 0 && data != NULL) + config.aliases = data; + else if (strcmp(word, "SPOOLDIR") == 0 && data != NULL) + config.spooldir = data; + else if (strcmp(word, "AUTHPATH") == 0 && data != NULL) + config.authpath= data; + else if (strcmp(word, "CERTFILE") == 0 && data != NULL) + config.certfile = data; + else if (strcmp(word, "MAILNAME") == 0 && data != NULL) + config.mailname = data; + else if (strcmp(word, "MASQUERADE") == 0 && data != NULL) { + char *user = NULL, *host = NULL; + if (strrchr(data, '@')) { + host = strrchr(data, '@'); + *host = 0; + host++; + user = data; + } else { + host = data; + } + if (host && *host == 0) + host = NULL; + if (user && *user == 0) + user = NULL; + config.masquerade_host = host; + config.masquerade_user = user; + } else if (strcmp(word, "STARTTLS") == 0 && data == NULL) + config.features |= STARTTLS; + else if (strcmp(word, "OPPORTUNISTIC_TLS") == 0 && data == NULL) + config.features |= TLS_OPP; + else if (strcmp(word, "SECURETRANSFER") == 0 && data == NULL) + config.features |= SECURETRANS; + else if (strcmp(word, "DEFER") == 0 && data == NULL) + config.features |= DEFER; + else if (strcmp(word, "INSECURE") == 0 && data == NULL) + config.features |= INSECURE; + else if (strcmp(word, "FULLBOUNCE") == 0 && data == NULL) + config.features |= FULLBOUNCE; + else if (strcmp(word, "NULLCLIENT") == 0 && data == NULL) + config.features |= NULLCLIENT; + else { + errlogx(EX_CONFIG, "syntax error in %s:%d", config_path, lineno); + /* NOTREACHED */ + } + } + + if ((config.features & NULLCLIENT) && config.smarthost == NULL) { + errlogx(EX_CONFIG, "%s: NULLCLIENT requires SMARTHOST", config_path); + /* NOTREACHED */ + } + + fclose(conf); +} Property changes on: vendor/dma/0.10/conf.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/dma-mbox-create.c =================================================================== --- vendor/dma/0.10/dma-mbox-create.c (nonexistent) +++ vendor/dma/0.10/dma-mbox-create.c (revision 289122) @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2010-2014, Simon Schubert <2@0x2c.org>. + * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Simon Schubert <2@0x2c.org>. + * + * 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. + */ + +/* + * This binary is setuid root. Use extreme caution when touching + * user-supplied information. Keep the root window as small as possible. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dma.h" + + +static void +logfail(int exitcode, const char *fmt, ...) +{ + int oerrno = errno; + va_list ap; + char outs[1024]; + + outs[0] = 0; + if (fmt != NULL) { + va_start(ap, fmt); + vsnprintf(outs, sizeof(outs), fmt, ap); + va_end(ap); + } + + errno = oerrno; + if (*outs != 0) + syslog(LOG_ERR, errno ? "%s: %m" : "%s", outs); + else + syslog(LOG_ERR, errno ? "%m" : "unknown error"); + + exit(exitcode); +} + +/* + * Create a mbox in /var/mail for a given user, or make sure + * the permissions are correct for dma. + */ + +int +main(int argc, char **argv) +{ + const char *user; + struct passwd *pw; + struct group *gr; + uid_t user_uid; + gid_t mail_gid; + int error; + char fn[PATH_MAX+1]; + int f; + + openlog("dma-mbox-create", 0, LOG_MAIL); + + errno = 0; + gr = getgrnam(DMA_GROUP); + if (!gr) + logfail(EX_CONFIG, "cannot find dma group `%s'", DMA_GROUP); + + mail_gid = gr->gr_gid; + + if (setgid(mail_gid) != 0) + logfail(EX_NOPERM, "cannot set gid to %d (%s)", mail_gid, DMA_GROUP); + if (getegid() != mail_gid) + logfail(EX_NOPERM, "cannot set gid to %d (%s), still at %d", mail_gid, DMA_GROUP, getegid()); + + /* + * We take exactly one argument: the username. + */ + if (argc != 2) { + errno = 0; + logfail(EX_USAGE, "no arguments"); + } + user = argv[1]; + + syslog(LOG_NOTICE, "creating mbox for `%s'", user); + + /* the username may not contain a pathname separator */ + if (strchr(user, '/')) { + errno = 0; + logfail(EX_DATAERR, "path separator in username `%s'", user); + exit(1); + } + + /* verify the user exists */ + errno = 0; + pw = getpwnam(user); + if (!pw) + logfail(EX_NOUSER, "cannot find user `%s'", user); + + user_uid = pw->pw_uid; + + error = snprintf(fn, sizeof(fn), "%s/%s", _PATH_MAILDIR, user); + if (error < 0 || (size_t)error >= sizeof(fn)) { + if (error >= 0) { + errno = 0; + logfail(EX_USAGE, "mbox path too long"); + } + logfail(EX_CANTCREAT, "cannot build mbox path for `%s/%s'", _PATH_MAILDIR, user); + } + + f = open(fn, O_RDONLY|O_CREAT, 0600); + if (f < 0) + logfail(EX_NOINPUT, "cannt open mbox `%s'", fn); + + if (fchown(f, user_uid, mail_gid)) + logfail(EX_OSERR, "cannot change owner of mbox `%s'", fn); + + if (fchmod(f, 0620)) + logfail(EX_OSERR, "cannot change permissions of mbox `%s'", fn); + + /* file should be present with the right owner and permissions */ + + syslog(LOG_NOTICE, "successfully created mbox for `%s'", user); + + return (0); +} Property changes on: vendor/dma/0.10/dma-mbox-create.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/dma.8 =================================================================== --- vendor/dma/0.10/dma.8 (nonexistent) +++ vendor/dma/0.10/dma.8 (revision 289122) @@ -0,0 +1,364 @@ +.\" +.\" Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>. +.\" Copyright (c) 2008 +.\" The DragonFly Project. All rights reserved. +.\" +.\" 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. +.\" +.Dd February 13, 2014 +.Dt DMA 8 +.Os +.Sh NAME +.Nm dma +.Nd DragonFly Mail Agent +.Sh SYNOPSIS +.Nm +.Op Fl DiOt +.Op Fl A Ns Ar mode +.Op Fl b Ns Ar mode +.Op Fl f Ar sender +.Op Fl L Ar tag +.Op Fl o Ns Ar option +.Op Fl r Ar sender +.Op Fl q Ns Op Ar arg +.Op Ar recipient ... +.Sh DESCRIPTION +.Nm +is a small Mail Transport Agent (MTA), designed for home and office use. +It accepts mails from locally installed Mail User Agents (MUA) and +delivers the mails either locally or to a remote destination. +Remote delivery includes several features like TLS/SSL support and SMTP +authentication. +.Pp +.Nm +is not intended as a replacement for real, big MTAs like +.Xr sendmail 8 +or +.Xr postfix 1 . +Consequently, +.Nm +does not listen on port 25 for incoming connections. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl A Ns Ar mode +.Fl \&Ac +acts as a compatibility option for sendmail. +.It Fl b Ns Ar mode +.Bl -tag -width indent +.It Fl bp +List all mails currently stored in the mail queue. +.It Fl bq +Queue the mail, but don't attempt to deliver it. +See also the +.Sq DEFER +config file setting below. +.El +.Pp +All other +.Ar mode Ns +s are are ignored. +.It Fl D +Don't run in the background. +Useful for debugging. +.It Fl f Ar sender +Set sender address (envelope-from) to +.Ar sender . +This overrides the value of the environment variable +.Ev EMAIL . +.It Fl i +Ignore dots alone on lines by themselves in incoming messages. +This should be set if you are reading data from a file. +.It Fl L Ar tag +Set the identifier used in syslog messages to the supplied +.Ar tag . +This is a compatibility option for sendmail. +.It Fl O +This is a compatibility option for sendmail. +.It Fl o Ns Ar option +Specifying +.Fl oi +is synonymous to +.Fl i . +All other options are ignored. +.It Fl q Ns Op Ar arg +Process saved messages in the queue. +The argument is optional and ignored. +.It Fl r Ar sender +Same as +.Fl f . +.It Fl t +Obtain recipient addresses from the message header. +.Nm +will parse the +.Li To: , +.Li Cc: , +and +.Li Bcc: +headers. +The +.Li Bcc: +header will be removed independent of whether +.Fl t +is specified or not. +.El +.Sh CONFIGURATION +.Nm +can be configured with two config files: +.Pp +.Bl -bullet -compact +.It +auth.conf +.It +dma.conf +.El +.Pp +These two files are stored per default in +.Pa /etc/dma . +.Sh FILE FORMAT +Every file contains parameters of the form +.Sq name value . +Lines containing boolean values are set to +.Sq NO +if the line is commented and to +.Sq YES +if the line is uncommented. +Empty lines or lines beginning with a +.Sq # +are ignored. +Parameter names and their values are case sensitive. +.Sh PARAMETERS +.Ss auth.conf +SMTP authentication can be configured in +.Pa auth.conf . +Each line has the format +.Dq Li user|smarthost:password . +.Ss dma.conf +Most of the behaviour of +.Nm +can be configured in +.Pa dma.conf . +.Bl -tag -width 4n +.It Ic SMARTHOST Xo +(string, default=empty) +.Xc +If you want to send outgoing mails via a smarthost, set this variable to +your smarthosts address. +.It Ic PORT Xo +(numeric, default=25) +.Xc +Use this port to deliver remote emails. +Only useful together with the +.Sq SMARTHOST +option, because +.Nm +will deliver all mails to this port, regardless of whether a smarthost is set +or not. +.It Ic ALIASES Xo +(string, default=/etc/aliases) +.Xc +Path to the local aliases file. +Just stick with the default. +The aliases file is of the format +.Dl nam: dest1 dest2 ... +In this case, mails to +.Li nam +will instead be delivered to +.Li dest1 +and +.Li dest2 , +which in turn could be entries in +.Pa /etc/aliases . +The special name +.Ql * +can be used to create a catch-all alias, which gets used if no other +matching alias is found. +Use the catch-all alias only if you don't want any local mail to be +delivered. +.It Ic SPOOLDIR Xo +(string, default=/var/spool/dma) +.Xc +Path to +.Nm Ap s +spool directory. +Just stick with the default. +.It Ic AUTHPATH Xo +(string, default=not set) +.Xc +Path to the +.Sq auth.conf +file. +.It Ic SECURETRANS Xo +(boolean, default=commented) +.Xc +Uncomment if you want TLS/SSL secured transfer. +.It Ic STARTTLS Xo +(boolean, default=commented) +.Xc +Uncomment if you want to use STARTTLS. +Only useful together with +.Sq SECURETRANS . +.It Ic OPPORTUNISTIC_TLS Xo +(boolean, default=commented) +.Xc +Uncomment if you want to allow the STARTTLS negotiation to fail. +Most useful when +.Nm +is used without a smarthost, delivering remote messages directly to +the outside mail exchangers; in opportunistic TLS mode, the connection will +be encrypted if the remote server supports STARTTLS, but an unencrypted +delivery will still be made if the negotiation fails. +Only useful together with +.Sq SECURETRANS +and +.Sq STARTTLS . +.It Ic CERTFILE Xo +(string, default=empty) +.Xc +Path to your SSL certificate file. +.It Ic SECURE Xo +(boolean, default=commented) +.Xc +Uncomment this entry and change it to +.Sq INSECURE +to use plain text SMTP login over an insecure connection. +You have to rename this variable manually to prevent that you send your +password accidentally over an insecure connection. +.It Ic DEFER Xo +(boolean, default=commented) +.Xc +Uncomment if you want that +.Nm +defers your mail. +You have to flush your mail queue manually with the +.Fl q +option. +This option is handy if you are behind a dialup line. +.It Ic FULLBOUNCE Xo +(boolean, default=commented) +.Xc +Uncomment if you want the bounce message to include the complete original +message, not just the headers. +.It Ic MAILNAME Xo +(string, default=empty) +.Xc +The internet hostname +.Nm +uses to identify the host. +If not set or empty, the result of +.Xr gethostname 3 +is used. +If +.Sq MAILNAME +is an absolute path to a file, the first line of this file will be used +as the hostname. +.It Ic MASQUERADE Xo +(string, default=empty) +.Xc +Masquerade the envelope-from addresses with this address/hostname. +Use this setting if mails are not accepted by destination mail servers +because your sender domain is invalid. +This setting is overridden by the +.Fl f +flag and the +.Ev EMAIL +environment variable. +.Pp +If +.Sq MASQUERADE +does not contain a +.Li @ +sign, the string is interpreted as a host name. +For example, setting +.Sq MASQUERADE +to +.Ql john@ +on host +.Ql hamlet +will send all mails as +.Ql john@hamlet ; +setting it to +.Ql percolator +will send all mails as +.Ql Sm off Va username @percolator . +.Sm on +.It Ic NULLCLIENT Xo +.Xc +Bypass aliases and local delivery, and instead forward all mails to +the defined +.Sq SMARTHOST . +.Sq NULLCLIENT +requires +.Sq SMARTHOST +to be set. +.El +.Ss Environment variables +The behavior of +.Nm +can be influenced by some environment variables. +.Bl -tag -width 4n +.It Ev EMAIL Xo +.Xc +Used to set the sender address (envelope-from). +Use a plain address, in the form of +.Li user@example.com . +This value will be overridden when the +.Fl f +flag is used. +.El +.Sh SEE ALSO +.Xr mailaddr 7 , +.Xr mailwrapper 8 , +.Xr sendmail 8 +.Rs +.%A "J. B. Postel" +.%T "Simple Mail Transfer Protocol" +.%O RFC 821 +.Re +.Rs +.%A "J. Myers" +.%T "SMTP Service Extension for Authentication" +.%O RFC 2554 +.Re +.Rs +.%A "P. Hoffman" +.%T "SMTP Service Extension for Secure SMTP over TLS" +.%O RFC 2487 +.Re +.Sh HISTORY +The +.Nm +utility first appeared in +.Dx 1.11 . +.Sh AUTHORS +.An -nosplit +.Nm +was written by +.An Matthias Schmidt Aq Mt matthias@dragonflybsd.org +and +.An Simon Schubert Aq Mt 2@0x2c.org . Property changes on: vendor/dma/0.10/dma.8 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/dma.c =================================================================== --- vendor/dma/0.10/dma.c (nonexistent) +++ vendor/dma/0.10/dma.c (revision 289122) @@ -0,0 +1,632 @@ +/* + * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>. + * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Simon Schubert <2@0x2c.org>. + * + * 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 "dfcompat.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dma.h" + + +static void deliver(struct qitem *); + +struct aliases aliases = LIST_HEAD_INITIALIZER(aliases); +struct strlist tmpfs = SLIST_HEAD_INITIALIZER(tmpfs); +struct authusers authusers = LIST_HEAD_INITIALIZER(authusers); +char username[USERNAME_SIZE]; +uid_t useruid; +const char *logident_base; +char errmsg[ERRMSG_SIZE]; + +static int daemonize = 1; +static int doqueue = 0; + +struct config config = { + .smarthost = NULL, + .port = 25, + .aliases = "/etc/aliases", + .spooldir = "/var/spool/dma", + .authpath = NULL, + .certfile = NULL, + .features = 0, + .mailname = NULL, + .masquerade_host = NULL, + .masquerade_user = NULL, +}; + + +static void +sighup_handler(int signo) +{ + (void)signo; /* so that gcc doesn't complain */ +} + +static char * +set_from(struct queue *queue, const char *osender) +{ + const char *addr; + char *sender; + + if (osender) { + addr = osender; + } else if (getenv("EMAIL") != NULL) { + addr = getenv("EMAIL"); + } else { + if (config.masquerade_user) + addr = config.masquerade_user; + else + addr = username; + } + + if (!strchr(addr, '@')) { + const char *from_host = hostname(); + + if (config.masquerade_host) + from_host = config.masquerade_host; + + if (asprintf(&sender, "%s@%s", addr, from_host) <= 0) + return (NULL); + } else { + sender = strdup(addr); + if (sender == NULL) + return (NULL); + } + + if (strchr(sender, '\n') != NULL) { + errno = EINVAL; + return (NULL); + } + + queue->sender = sender; + return (sender); +} + +static int +read_aliases(void) +{ + yyin = fopen(config.aliases, "r"); + if (yyin == NULL) { + /* + * Non-existing aliases file is not a fatal error + */ + if (errno == ENOENT) + return (0); + /* Other problems are. */ + return (-1); + } + if (yyparse()) + return (-1); /* fatal error, probably malloc() */ + fclose(yyin); + return (0); +} + +static int +do_alias(struct queue *queue, const char *addr) +{ + struct alias *al; + struct stritem *sit; + int aliased = 0; + + LIST_FOREACH(al, &aliases, next) { + if (strcmp(al->alias, addr) != 0) + continue; + SLIST_FOREACH(sit, &al->dests, next) { + if (add_recp(queue, sit->str, EXPAND_ADDR) != 0) + return (-1); + } + aliased = 1; + } + + return (aliased); +} + +int +add_recp(struct queue *queue, const char *str, int expand) +{ + struct qitem *it, *tit; + struct passwd *pw; + char *host; + int aliased = 0; + + it = calloc(1, sizeof(*it)); + if (it == NULL) + return (-1); + it->addr = strdup(str); + if (it->addr == NULL) + return (-1); + + it->sender = queue->sender; + host = strrchr(it->addr, '@'); + if (host != NULL && + (strcmp(host + 1, hostname()) == 0 || + strcmp(host + 1, "localhost") == 0)) { + *host = 0; + } + LIST_FOREACH(tit, &queue->queue, next) { + /* weed out duplicate dests */ + if (strcmp(tit->addr, it->addr) == 0) { + free(it->addr); + free(it); + return (0); + } + } + LIST_INSERT_HEAD(&queue->queue, it, next); + + /** + * Do local delivery if there is no @. + * Do not do local delivery when NULLCLIENT is set. + */ + if (strrchr(it->addr, '@') == NULL && (config.features & NULLCLIENT) == 0) { + it->remote = 0; + if (expand) { + aliased = do_alias(queue, it->addr); + if (!aliased && expand == EXPAND_WILDCARD) + aliased = do_alias(queue, "*"); + if (aliased < 0) + return (-1); + if (aliased) { + LIST_REMOVE(it, next); + } else { + /* Local destination, check */ + pw = getpwnam(it->addr); + if (pw == NULL) + goto out; + /* XXX read .forward */ + endpwent(); + } + } + } else { + it->remote = 1; + } + + return (0); + +out: + free(it->addr); + free(it); + return (-1); +} + +static struct qitem * +go_background(struct queue *queue) +{ + struct sigaction sa; + struct qitem *it; + pid_t pid; + + if (daemonize && daemon(0, 0) != 0) { + syslog(LOG_ERR, "can not daemonize: %m"); + exit(EX_OSERR); + } + daemonize = 0; + + bzero(&sa, sizeof(sa)); + sa.sa_handler = SIG_IGN; + sigaction(SIGCHLD, &sa, NULL); + + LIST_FOREACH(it, &queue->queue, next) { + /* No need to fork for the last dest */ + if (LIST_NEXT(it, next) == NULL) + goto retit; + + pid = fork(); + switch (pid) { + case -1: + syslog(LOG_ERR, "can not fork: %m"); + exit(EX_OSERR); + break; + + case 0: + /* + * Child: + * + * return and deliver mail + */ +retit: + /* + * If necessary, acquire the queue and * mail files. + * If this fails, we probably were raced by another + * process. It is okay to be raced if we're supposed + * to flush the queue. + */ + setlogident("%s", it->queueid); + switch (acquirespool(it)) { + case 0: + break; + case 1: + if (doqueue) + exit(EX_OK); + syslog(LOG_WARNING, "could not lock queue file"); + exit(EX_SOFTWARE); + default: + exit(EX_SOFTWARE); + } + dropspool(queue, it); + return (it); + + default: + /* + * Parent: + * + * fork next child + */ + break; + } + } + + syslog(LOG_CRIT, "reached dead code"); + exit(EX_SOFTWARE); +} + +static void +deliver(struct qitem *it) +{ + int error; + unsigned int backoff = MIN_RETRY, slept; + struct timeval now; + struct stat st; + + snprintf(errmsg, sizeof(errmsg), "unknown bounce reason"); + +retry: + syslog(LOG_INFO, "trying delivery"); + + if (it->remote) + error = deliver_remote(it); + else + error = deliver_local(it); + + switch (error) { + case 0: + delqueue(it); + syslog(LOG_INFO, "delivery successful"); + exit(EX_OK); + + case 1: + if (stat(it->queuefn, &st) != 0) { + syslog(LOG_ERR, "lost queue file `%s'", it->queuefn); + exit(EX_SOFTWARE); + } + if (gettimeofday(&now, NULL) == 0 && + (now.tv_sec - st.st_mtim.tv_sec > MAX_TIMEOUT)) { + snprintf(errmsg, sizeof(errmsg), + "Could not deliver for the last %d seconds. Giving up.", + MAX_TIMEOUT); + goto bounce; + } + for (slept = 0; slept < backoff;) { + slept += SLEEP_TIMEOUT - sleep(SLEEP_TIMEOUT); + if (flushqueue_since(slept)) { + backoff = MIN_RETRY; + goto retry; + } + } + if (slept >= backoff) { + /* pick the next backoff between [1.5, 2.5) times backoff */ + backoff = backoff + backoff / 2 + random() % backoff; + if (backoff > MAX_RETRY) + backoff = MAX_RETRY; + } + goto retry; + + case -1: + default: + break; + } + +bounce: + bounce(it, errmsg); + /* NOTREACHED */ +} + +void +run_queue(struct queue *queue) +{ + struct qitem *it; + + if (LIST_EMPTY(&queue->queue)) + return; + + it = go_background(queue); + deliver(it); + /* NOTREACHED */ +} + +static void +show_queue(struct queue *queue) +{ + struct qitem *it; + int locked = 0; /* XXX */ + + if (LIST_EMPTY(&queue->queue)) { + printf("Mail queue is empty\n"); + return; + } + + LIST_FOREACH(it, &queue->queue, next) { + printf("ID\t: %s%s\n" + "From\t: %s\n" + "To\t: %s\n", + it->queueid, + locked ? "*" : "", + it->sender, it->addr); + + if (LIST_NEXT(it, next) != NULL) + printf("--\n"); + } +} + +/* + * TODO: + * + * - alias processing + * - use group permissions + * - proper sysexit codes + */ + +int +main(int argc, char **argv) +{ + struct sigaction act; + char *sender = NULL; + struct queue queue; + int i, ch; + int nodot = 0, showq = 0, queue_only = 0; + int recp_from_header = 0; + + set_username(); + + /* + * We never run as root. If called by root, drop permissions + * to the mail user. + */ + if (geteuid() == 0 || getuid() == 0) { + struct passwd *pw; + + errno = 0; + pw = getpwnam(DMA_ROOT_USER); + if (pw == NULL) { + if (errno == 0) + errx(EX_CONFIG, "user '%s' not found", DMA_ROOT_USER); + else + err(EX_OSERR, "cannot drop root privileges"); + } + + if (setuid(pw->pw_uid) != 0) + err(EX_OSERR, "cannot drop root privileges"); + + if (geteuid() == 0 || getuid() == 0) + errx(EX_OSERR, "cannot drop root privileges"); + } + + atexit(deltmp); + init_random(); + + bzero(&queue, sizeof(queue)); + LIST_INIT(&queue.queue); + + if (strcmp(argv[0], "mailq") == 0) { + argv++; argc--; + showq = 1; + if (argc != 0) + errx(EX_USAGE, "invalid arguments"); + goto skipopts; + } else if (strcmp(argv[0], "newaliases") == 0) { + logident_base = "dma"; + setlogident(NULL); + + if (read_aliases() != 0) + errx(EX_SOFTWARE, "could not parse aliases file `%s'", config.aliases); + exit(EX_OK); + } + + opterr = 0; + while ((ch = getopt(argc, argv, ":A:b:B:C:d:Df:F:h:iL:N:no:O:q:r:R:tUV:vX:")) != -1) { + switch (ch) { + case 'A': + /* -AX is being ignored, except for -A{c,m} */ + if (optarg[0] == 'c' || optarg[0] == 'm') { + break; + } + /* else FALLTRHOUGH */ + case 'b': + /* -bX is being ignored, except for -bp */ + if (optarg[0] == 'p') { + showq = 1; + break; + } else if (optarg[0] == 'q') { + queue_only = 1; + break; + } + /* else FALLTRHOUGH */ + case 'D': + daemonize = 0; + break; + case 'L': + logident_base = optarg; + break; + case 'f': + case 'r': + sender = optarg; + break; + + case 't': + recp_from_header = 1; + break; + + case 'o': + /* -oX is being ignored, except for -oi */ + if (optarg[0] != 'i') + break; + /* else FALLTRHOUGH */ + case 'O': + break; + case 'i': + nodot = 1; + break; + + case 'q': + /* Don't let getopt slup up other arguments */ + if (optarg && *optarg == '-') + optind--; + doqueue = 1; + break; + + /* Ignored options */ + case 'B': + case 'C': + case 'd': + case 'F': + case 'h': + case 'N': + case 'n': + case 'R': + case 'U': + case 'V': + case 'v': + case 'X': + break; + + case ':': + if (optopt == 'q') { + doqueue = 1; + break; + } + /* FALLTHROUGH */ + + default: + fprintf(stderr, "invalid argument: `-%c'\n", optopt); + exit(EX_USAGE); + } + } + argc -= optind; + argv += optind; + opterr = 1; + + if (argc != 0 && (showq || doqueue)) + errx(EX_USAGE, "sending mail and queue operations are mutually exclusive"); + + if (showq + doqueue > 1) + errx(EX_USAGE, "conflicting queue operations"); + +skipopts: + if (logident_base == NULL) + logident_base = "dma"; + setlogident(NULL); + + act.sa_handler = sighup_handler; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + if (sigaction(SIGHUP, &act, NULL) != 0) + syslog(LOG_WARNING, "can not set signal handler: %m"); + + parse_conf(CONF_PATH "/dma.conf"); + + if (config.authpath != NULL) + parse_authfile(config.authpath); + + if (showq) { + if (load_queue(&queue) < 0) + errlog(EX_NOINPUT, "can not load queue"); + show_queue(&queue); + return (0); + } + + if (doqueue) { + flushqueue_signal(); + if (load_queue(&queue) < 0) + errlog(EX_NOINPUT, "can not load queue"); + run_queue(&queue); + return (0); + } + + if (read_aliases() != 0) + errlog(EX_SOFTWARE, "could not parse aliases file `%s'", config.aliases); + + if ((sender = set_from(&queue, sender)) == NULL) + errlog(EX_SOFTWARE, NULL); + + if (newspoolf(&queue) != 0) + errlog(EX_CANTCREAT, "can not create temp file in `%s'", config.spooldir); + + setlogident("%s", queue.id); + + for (i = 0; i < argc; i++) { + if (add_recp(&queue, argv[i], EXPAND_WILDCARD) != 0) + errlogx(EX_DATAERR, "invalid recipient `%s'", argv[i]); + } + + if (LIST_EMPTY(&queue.queue) && !recp_from_header) + errlogx(EX_NOINPUT, "no recipients"); + + if (readmail(&queue, nodot, recp_from_header) != 0) + errlog(EX_NOINPUT, "can not read mail"); + + if (LIST_EMPTY(&queue.queue)) + errlogx(EX_NOINPUT, "no recipients"); + + if (linkspool(&queue) != 0) + errlog(EX_CANTCREAT, "can not create spools"); + + /* From here on the mail is safe. */ + + if (config.features & DEFER || queue_only) + return (0); + + run_queue(&queue); + + /* NOTREACHED */ + return (0); +} Property changes on: vendor/dma/0.10/dma.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/dma.h =================================================================== --- vendor/dma/0.10/dma.h (nonexistent) +++ vendor/dma/0.10/dma.h (revision 289122) @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>. + * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Simon Schubert <2@0x2c.org> and + * Matthias Schmidt . + * + * 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. + */ + +#ifndef DMA_H +#define DMA_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#define VERSION "DragonFly Mail Agent " DMA_VERSION + +#define BUF_SIZE 2048 +#define ERRMSG_SIZE 200 +#define USERNAME_SIZE 50 +#define MIN_RETRY 300 /* 5 minutes */ +#define MAX_RETRY (3*60*60) /* retry at least every 3 hours */ +#define MAX_TIMEOUT (5*24*60*60) /* give up after 5 days */ +#define SLEEP_TIMEOUT 30 /* check for queue flush every 30 seconds */ +#ifndef PATH_MAX +#define PATH_MAX 1024 /* Max path len */ +#endif +#define SMTP_PORT 25 /* Default SMTP port */ +#define CON_TIMEOUT (5*60) /* Connection timeout per RFC5321 */ + +#define STARTTLS 0x002 /* StartTLS support */ +#define SECURETRANS 0x004 /* SSL/TLS in general */ +#define NOSSL 0x008 /* Do not use SSL */ +#define DEFER 0x010 /* Defer mails */ +#define INSECURE 0x020 /* Allow plain login w/o encryption */ +#define FULLBOUNCE 0x040 /* Bounce the full message */ +#define TLS_OPP 0x080 /* Opportunistic STARTTLS */ +#define NULLCLIENT 0x100 /* Nullclient support */ + +#ifndef CONF_PATH +#error Please define CONF_PATH +#endif + +#ifndef LIBEXEC_PATH +#error Please define LIBEXEC_PATH +#endif + +#define SPOOL_FLUSHFILE "flush" + +#ifndef DMA_ROOT_USER +#define DMA_ROOT_USER "mail" +#endif +#ifndef DMA_GROUP +#define DMA_GROUP "mail" +#endif + +#ifndef MBOX_STRICT +#define MBOX_STRICT 0 +#endif + + +struct stritem { + SLIST_ENTRY(stritem) next; + char *str; +}; +SLIST_HEAD(strlist, stritem); + +struct alias { + LIST_ENTRY(alias) next; + char *alias; + struct strlist dests; +}; +LIST_HEAD(aliases, alias); + +struct qitem { + LIST_ENTRY(qitem) next; + const char *sender; + char *addr; + char *queuefn; + char *mailfn; + char *queueid; + FILE *queuef; + FILE *mailf; + int remote; +}; +LIST_HEAD(queueh, qitem); + +struct queue { + struct queueh queue; + char *id; + FILE *mailf; + char *tmpf; + const char *sender; +}; + +struct config { + const char *smarthost; + int port; + const char *aliases; + const char *spooldir; + const char *authpath; + const char *certfile; + int features; + const char *mailname; + const char *masquerade_host; + const char *masquerade_user; + + /* XXX does not belong into config */ + SSL *ssl; +}; + + +struct authuser { + SLIST_ENTRY(authuser) next; + char *login; + char *password; + char *host; +}; +SLIST_HEAD(authusers, authuser); + + +struct mx_hostentry { + char host[MAXDNAME]; + char addr[INET6_ADDRSTRLEN]; + int pref; + struct addrinfo ai; + struct sockaddr_storage sa; +}; + + +/* global variables */ +extern struct aliases aliases; +extern struct config config; +extern struct strlist tmpfs; +extern struct authusers authusers; +extern char username[USERNAME_SIZE]; +extern uid_t useruid; +extern const char *logident_base; + +extern char neterr[ERRMSG_SIZE]; +extern char errmsg[ERRMSG_SIZE]; + +/* aliases_parse.y */ +int yyparse(void); +int yywrap(void); +int yylex(void); +extern FILE *yyin; + +/* conf.c */ +void trim_line(char *); +void parse_conf(const char *); +void parse_authfile(const char *); + +/* crypto.c */ +void hmac_md5(unsigned char *, int, unsigned char *, int, unsigned char *); +int smtp_auth_md5(int, char *, char *); +int smtp_init_crypto(int, int); + +/* dns.c */ +int dns_get_mx_list(const char *, int, struct mx_hostentry **, int); + +/* net.c */ +char *ssl_errstr(void); +int read_remote(int, int, char *); +ssize_t send_remote_command(int, const char*, ...) __attribute__((__nonnull__(2), __format__ (__printf__, 2, 3))); +int deliver_remote(struct qitem *); + +/* base64.c */ +int base64_encode(const void *, int, char **); +int base64_decode(const char *, void *); + +/* dma.c */ +#define EXPAND_ADDR 1 +#define EXPAND_WILDCARD 2 +int add_recp(struct queue *, const char *, int); +void run_queue(struct queue *); + +/* spool.c */ +int newspoolf(struct queue *); +int linkspool(struct queue *); +int load_queue(struct queue *); +void delqueue(struct qitem *); +int acquirespool(struct qitem *); +void dropspool(struct queue *, struct qitem *); +int flushqueue_since(unsigned int); +int flushqueue_signal(void); + +/* local.c */ +int deliver_local(struct qitem *); + +/* mail.c */ +void bounce(struct qitem *, const char *); +int readmail(struct queue *, int, int); + +/* util.c */ +const char *hostname(void); +void setlogident(const char *, ...) __attribute__((__format__ (__printf__, 1, 2))); +void errlog(int, const char *, ...) __attribute__((__format__ (__printf__, 2, 3))); +void errlogx(int, const char *, ...) __attribute__((__format__ (__printf__, 2, 3))); +void set_username(void); +void deltmp(void); +int do_timeout(int, int); +int open_locked(const char *, int, ...); +char *rfc822date(void); +int strprefixcmp(const char *, const char *); +void init_random(void); + +#endif Property changes on: vendor/dma/0.10/dma.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/dns.c =================================================================== --- vendor/dma/0.10/dns.c (nonexistent) +++ vendor/dma/0.10/dns.c (revision 289122) @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>. + * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Simon Schubert <2@0x2c.org>. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dma.h" + +static int +sort_pref(const void *a, const void *b) +{ + const struct mx_hostentry *ha = a, *hb = b; + int v; + + /* sort increasing by preference primarily */ + v = ha->pref - hb->pref; + if (v != 0) + return (v); + + /* sort PF_INET6 before PF_INET */ + v = - (ha->ai.ai_family - hb->ai.ai_family); + return (v); +} + +static int +add_host(int pref, const char *host, int port, struct mx_hostentry **he, size_t *ps) +{ + struct addrinfo hints, *res, *res0 = NULL; + char servname[10]; + struct mx_hostentry *p; + const int count_inc = 10; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + snprintf(servname, sizeof(servname), "%d", port); + switch (getaddrinfo(host, servname, &hints, &res0)) { + case 0: + break; + case EAI_AGAIN: + case EAI_NONAME: + /* + * EAI_NONAME gets returned for: + * SMARTHOST set but DNS server not reachable -> defer + * SMARTHOST set but DNS server returns "host does not exist" + * -> buggy configuration + * -> either defer or bounce would be ok -> defer + * MX entry was returned by DNS server but name doesn't resolve + * -> hopefully transient situation -> defer + * all other DNS problems should have been caught earlier + * in dns_get_mx_list(). + */ + goto out; + default: + return(-1); + } + + for (res = res0; res != NULL; res = res->ai_next) { + if (*ps + 1 >= roundup(*ps, count_inc)) { + size_t newsz = roundup(*ps + 2, count_inc); + *he = reallocf(*he, newsz * sizeof(**he)); + if (*he == NULL) + goto out; + } + + p = &(*he)[*ps]; + strlcpy(p->host, host, sizeof(p->host)); + p->pref = pref; + p->ai = *res; + p->ai.ai_addr = NULL; + bcopy(res->ai_addr, &p->sa, p->ai.ai_addrlen); + + getnameinfo((struct sockaddr *)&p->sa, p->ai.ai_addrlen, + p->addr, sizeof(p->addr), + NULL, 0, NI_NUMERICHOST); + + (*ps)++; + } + freeaddrinfo(res0); + + return (0); + +out: + if (res0 != NULL) + freeaddrinfo(res0); + return (1); +} + +int +dns_get_mx_list(const char *host, int port, struct mx_hostentry **he, int no_mx) +{ + char outname[MAXDNAME]; + ns_msg msg; + ns_rr rr; + const char *searchhost; + const unsigned char *cp; + unsigned char *ans; + struct mx_hostentry *hosts = NULL; + size_t nhosts = 0; + size_t anssz; + int pref; + int cname_recurse; + int have_mx = 0; + int err; + int i; + + res_init(); + searchhost = host; + cname_recurse = 0; + + anssz = 65536; + ans = malloc(anssz); + if (ans == NULL) + return (1); + + if (no_mx) + goto out; + +repeat: + err = res_search(searchhost, ns_c_in, ns_t_mx, ans, anssz); + if (err < 0) { + switch (h_errno) { + case NO_DATA: + /* + * Host exists, but no MX (or CNAME) entry. + * Not an error, use host name instead. + */ + goto out; + case TRY_AGAIN: + /* transient error */ + goto transerr; + case NO_RECOVERY: + case HOST_NOT_FOUND: + default: + errno = ENOENT; + goto err; + } + } + + if (!ns_initparse(ans, anssz, &msg)) + goto transerr; + + switch (ns_msg_getflag(msg, ns_f_rcode)) { + case ns_r_noerror: + break; + case ns_r_nxdomain: + goto err; + default: + goto transerr; + } + + for (i = 0; i < ns_msg_count(msg, ns_s_an); i++) { + if (ns_parserr(&msg, ns_s_an, i, &rr)) + goto transerr; + + cp = ns_rr_rdata(rr); + + switch (ns_rr_type(rr)) { + case ns_t_mx: + have_mx = 1; + pref = ns_get16(cp); + cp += 2; + err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg), + cp, outname, sizeof(outname)); + if (err < 0) + goto transerr; + + err = add_host(pref, outname, port, &hosts, &nhosts); + if (err == -1) + goto err; + break; + + case ns_t_cname: + err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg), + cp, outname, sizeof(outname)); + if (err < 0) + goto transerr; + + /* Prevent a CNAME loop */ + if (cname_recurse++ > 10) + goto err; + + searchhost = outname; + goto repeat; + + default: + break; + } + } + +out: + err = 0; + if (0) { +transerr: + if (nhosts == 0) + err = 1; + } + if (0) { +err: + err = -1; + } + + free(ans); + + if (err == 0) { + if (!have_mx) { + /* + * If we didn't find any MX, use the hostname instead. + */ + err = add_host(0, host, port, &hosts, &nhosts); + } else if (nhosts == 0) { + /* + * We did get MX, but couldn't resolve any of them + * due to transient errors. + */ + err = 1; + } + } + + if (nhosts > 0) { + qsort(hosts, nhosts, sizeof(*hosts), sort_pref); + /* terminate list */ + *hosts[nhosts].host = 0; + } else { + if (hosts != NULL) + free(hosts); + hosts = NULL; + } + + *he = hosts; + return (err); + + free(ans); + if (hosts != NULL) + free(hosts); + return (err); +} + +#if defined(TESTING) +int +main(int argc, char **argv) +{ + struct mx_hostentry *he, *p; + int err; + + err = dns_get_mx_list(argv[1], 53, &he, 0); + if (err) + return (err); + + for (p = he; *p->host != 0; p++) { + printf("%d\t%s\t%s\n", p->pref, p->host, p->addr); + } + + return (0); +} +#endif Property changes on: vendor/dma/0.10/dns.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/get-version.sh =================================================================== --- vendor/dma/0.10/get-version.sh (nonexistent) +++ vendor/dma/0.10/get-version.sh (revision 289122) @@ -0,0 +1,11 @@ +#!/bin/sh + +tmp=$1 +file=${tmp:=VERSION} +gitver=$(git describe 2>/dev/null | tr - .) +filever=$(cat ${file} 2>/dev/null) + +version=${gitver} +: ${version:=$filever} + +echo "$version" Property changes on: vendor/dma/0.10/get-version.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/local.c =================================================================== --- vendor/dma/0.10/local.c (nonexistent) +++ vendor/dma/0.10/local.c (revision 289122) @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>. + * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Simon Schubert <2@0x2c.org>. + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dma.h" + +static int +create_mbox(const char *name) +{ + struct sigaction sa, osa; + pid_t child, waitchild; + int status; + int i; + long maxfd; + int e; + int r = -1; + + /* + * We need to enable SIGCHLD temporarily so that waitpid works. + */ + bzero(&sa, sizeof(sa)); + sa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &sa, &osa); + + do_timeout(100, 0); + + child = fork(); + switch (child) { + case 0: + /* child */ + maxfd = sysconf(_SC_OPEN_MAX); + if (maxfd == -1) + maxfd = 1024; /* what can we do... */ + + for (i = 3; i <= maxfd; ++i) + close(i); + + execl(LIBEXEC_PATH "/dma-mbox-create", "dma-mbox-create", name, NULL); + syslog(LOG_ERR, "cannot execute "LIBEXEC_PATH"/dma-mbox-create: %m"); + exit(EX_SOFTWARE); + + default: + /* parent */ + waitchild = waitpid(child, &status, 0); + + e = errno; + + do_timeout(0, 0); + + if (waitchild == -1 && e == EINTR) { + syslog(LOG_ERR, "hung child while creating mbox `%s': %m", name); + break; + } + + if (waitchild == -1) { + syslog(LOG_ERR, "child disappeared while creating mbox `%s': %m", name); + break; + } + + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + syslog(LOG_ERR, "error creating mbox `%s'", name); + break; + } + + /* success */ + r = 0; + break; + + case -1: + /* error */ + syslog(LOG_ERR, "error creating mbox"); + break; + } + + sigaction(SIGCHLD, &osa, NULL); + + return (r); +} + +int +deliver_local(struct qitem *it) +{ + char fn[PATH_MAX+1]; + char line[1000]; + const char *sender; + const char *newline = "\n"; + size_t linelen; + int tries = 0; + int mbox; + int error; + int hadnl = 0; + off_t mboxlen; + time_t now = time(NULL); + + error = snprintf(fn, sizeof(fn), "%s/%s", _PATH_MAILDIR, it->addr); + if (error < 0 || (size_t)error >= sizeof(fn)) { + syslog(LOG_NOTICE, "local delivery deferred: %m"); + return (1); + } + +retry: + /* wait for a maximum of 100s to get the lock to the file */ + do_timeout(100, 0); + + /* don't use O_CREAT here, because we might be running as the wrong user. */ + mbox = open_locked(fn, O_WRONLY|O_APPEND); + if (mbox < 0) { + int e = errno; + + do_timeout(0, 0); + + switch (e) { + case EACCES: + case ENOENT: + /* + * The file does not exist or we can't access it. + * Call dma-mbox-create to create it and fix permissions. + */ + if (tries > 0 || create_mbox(it->addr) != 0) { + syslog(LOG_ERR, "local delivery deferred: can not create `%s'", fn); + return (1); + } + ++tries; + goto retry; + + case EINTR: + syslog(LOG_NOTICE, "local delivery deferred: can not lock `%s'", fn); + break; + + default: + syslog(LOG_NOTICE, "local delivery deferred: can not open `%s': %m", fn); + break; + } + return (1); + } + do_timeout(0, 0); + + mboxlen = lseek(mbox, 0, SEEK_END); + + /* New mails start with \nFrom ...., unless we're at the beginning of the mbox */ + if (mboxlen == 0) + newline = ""; + + /* If we're bouncing a message, claim it comes from MAILER-DAEMON */ + sender = it->sender; + if (strcmp(sender, "") == 0) + sender = "MAILER-DAEMON"; + + if (fseek(it->mailf, 0, SEEK_SET) != 0) { + syslog(LOG_NOTICE, "local delivery deferred: can not seek: %m"); + goto out; + } + + error = snprintf(line, sizeof(line), "%sFrom %s\t%s", newline, sender, ctime(&now)); + if (error < 0 || (size_t)error >= sizeof(line)) { + syslog(LOG_NOTICE, "local delivery deferred: can not write header: %m"); + goto out; + } + if (write(mbox, line, error) != error) + goto wrerror; + + while (!feof(it->mailf)) { + if (fgets(line, sizeof(line), it->mailf) == NULL) + break; + linelen = strlen(line); + if (linelen == 0 || line[linelen - 1] != '\n') { + syslog(LOG_CRIT, "local delivery failed: corrupted queue file"); + snprintf(errmsg, sizeof(errmsg), "corrupted queue file"); + error = -1; + goto chop; + } + + /* + * mboxro processing: + * - escape lines that start with "From " with a > sign. + * - be reversable by escaping lines that contain an arbitrary + * number of > signs, followed by "From ", i.e. />*From / in regexp. + * - strict mbox processing only requires escaping after empty lines, + * yet most MUAs seem to relax this requirement and will treat any + * line starting with "From " as the beginning of a new mail. + */ + if ((!MBOX_STRICT || hadnl) && + strncmp(&line[strspn(line, ">")], "From ", 5) == 0) { + const char *gt = ">"; + + if (write(mbox, gt, 1) != 1) + goto wrerror; + hadnl = 0; + } else if (strcmp(line, "\n") == 0) { + hadnl = 1; + } else { + hadnl = 0; + } + if ((size_t)write(mbox, line, linelen) != linelen) + goto wrerror; + } + close(mbox); + return (0); + +wrerror: + syslog(LOG_ERR, "local delivery failed: write error: %m"); + error = 1; +chop: + if (ftruncate(mbox, mboxlen) != 0) + syslog(LOG_WARNING, "error recovering mbox `%s': %m", fn); +out: + close(mbox); + return (error); +} Property changes on: vendor/dma/0.10/local.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/mail.c =================================================================== --- vendor/dma/0.10/mail.c (nonexistent) +++ vendor/dma/0.10/mail.c (revision 289122) @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>. + * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Simon Schubert <2@0x2c.org>. + * + * 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 +#include +#include +#include +#include + +#include "dma.h" + +void +bounce(struct qitem *it, const char *reason) +{ + struct queue bounceq; + char line[1000]; + size_t pos; + int error; + + /* Don't bounce bounced mails */ + if (it->sender[0] == 0) { + syslog(LOG_INFO, "can not bounce a bounce message, discarding"); + exit(EX_SOFTWARE); + } + + bzero(&bounceq, sizeof(bounceq)); + LIST_INIT(&bounceq.queue); + bounceq.sender = ""; + if (add_recp(&bounceq, it->sender, EXPAND_WILDCARD) != 0) + goto fail; + + if (newspoolf(&bounceq) != 0) + goto fail; + + syslog(LOG_ERR, "delivery failed, bouncing as %s", bounceq.id); + setlogident("%s", bounceq.id); + + error = fprintf(bounceq.mailf, + "Received: from MAILER-DAEMON\n" + "\tid %s\n" + "\tby %s (%s);\n" + "\t%s\n" + "X-Original-To: <%s>\n" + "From: MAILER-DAEMON <>\n" + "To: %s\n" + "Subject: Mail delivery failed\n" + "Message-Id: <%s@%s>\n" + "Date: %s\n" + "\n" + "This is the %s at %s.\n" + "\n" + "There was an error delivering your mail to <%s>.\n" + "\n" + "%s\n" + "\n" + "%s\n" + "\n", + bounceq.id, + hostname(), VERSION, + rfc822date(), + it->addr, + it->sender, + bounceq.id, hostname(), + rfc822date(), + VERSION, hostname(), + it->addr, + reason, + config.features & FULLBOUNCE ? + "Original message follows." : + "Message headers follow."); + if (error < 0) + goto fail; + + if (fseek(it->mailf, 0, SEEK_SET) != 0) + goto fail; + if (config.features & FULLBOUNCE) { + while ((pos = fread(line, 1, sizeof(line), it->mailf)) > 0) { + if (fwrite(line, 1, pos, bounceq.mailf) != pos) + goto fail; + } + } else { + while (!feof(it->mailf)) { + if (fgets(line, sizeof(line), it->mailf) == NULL) + break; + if (line[0] == '\n') + break; + if (fwrite(line, strlen(line), 1, bounceq.mailf) != 1) + goto fail; + } + } + + if (linkspool(&bounceq) != 0) + goto fail; + /* bounce is safe */ + + delqueue(it); + + run_queue(&bounceq); + /* NOTREACHED */ + +fail: + syslog(LOG_CRIT, "error creating bounce: %m"); + delqueue(it); + exit(EX_IOERR); +} + +struct parse_state { + char addr[1000]; + int pos; + + enum { + NONE = 0, + START, + MAIN, + EOL, + QUIT + } state; + int comment; + int quote; + int brackets; + int esc; +}; + +/* + * Simplified RFC2822 header/address parsing. + * We copy escapes and quoted strings directly, since + * we have to pass them like this to the mail server anyways. + * XXX local addresses will need treatment + */ +static int +parse_addrs(struct parse_state *ps, char *s, struct queue *queue) +{ + char *addr; + +again: + switch (ps->state) { + case NONE: + return (-1); + + case START: + /* init our data */ + bzero(ps, sizeof(*ps)); + + /* skip over header name */ + while (*s != ':') + s++; + s++; + ps->state = MAIN; + break; + + case MAIN: + /* all fine */ + break; + + case EOL: + switch (*s) { + case ' ': + case '\t': + s++; + /* continue */ + break; + + default: + ps->state = QUIT; + if (ps->pos != 0) + goto newaddr; + return (0); + } + + case QUIT: + return (0); + } + + for (; *s != 0; s++) { + if (ps->esc) { + ps->esc = 0; + + switch (*s) { + case '\r': + case '\n': + goto err; + + default: + goto copy; + } + } + + if (ps->quote) { + switch (*s) { + case '"': + ps->quote = 0; + goto copy; + + case '\\': + ps->esc = 1; + goto copy; + + case '\r': + case '\n': + goto eol; + + default: + goto copy; + } + } + + switch (*s) { + case '(': + ps->comment++; + break; + + case ')': + if (ps->comment) + ps->comment--; + else + goto err; + goto skip; + + case '"': + ps->quote = 1; + goto copy; + + case '\\': + ps->esc = 1; + goto copy; + + case '\r': + case '\n': + goto eol; + } + + if (ps->comment) + goto skip; + + switch (*s) { + case ' ': + case '\t': + /* ignore whitespace */ + goto skip; + + case '<': + /* this is the real address now */ + ps->brackets = 1; + ps->pos = 0; + goto skip; + + case '>': + if (!ps->brackets) + goto err; + ps->brackets = 0; + + s++; + goto newaddr; + + case ':': + /* group - ignore */ + ps->pos = 0; + goto skip; + + case ',': + case ';': + /* + * Next address, copy previous one. + * However, we might be directly after + * a
, or have two consecutive + * commas. + * Skip the comma unless there is + * really something to copy. + */ + if (ps->pos == 0) + goto skip; + s++; + goto newaddr; + + default: + goto copy; + } + +copy: + if (ps->comment) + goto skip; + + if (ps->pos + 1 == sizeof(ps->addr)) + goto err; + ps->addr[ps->pos++] = *s; + +skip: + ; + } + +eol: + ps->state = EOL; + return (0); + +err: + ps->state = QUIT; + return (-1); + +newaddr: + ps->addr[ps->pos] = 0; + ps->pos = 0; + addr = strdup(ps->addr); + if (addr == NULL) + errlog(EX_SOFTWARE, NULL); + + if (add_recp(queue, addr, EXPAND_WILDCARD) != 0) + errlogx(EX_DATAERR, "invalid recipient `%s'", addr); + + goto again; +} + +int +readmail(struct queue *queue, int nodot, int recp_from_header) +{ + struct parse_state parse_state; + char line[1000]; /* by RFC2822 */ + size_t linelen; + size_t error; + int had_headers = 0; + int had_from = 0; + int had_messagid = 0; + int had_date = 0; + int had_last_line = 0; + int nocopy = 0; + + parse_state.state = NONE; + + error = fprintf(queue->mailf, + "Received: from %s (uid %d)\n" + "\t(envelope-from %s)\n" + "\tid %s\n" + "\tby %s (%s);\n" + "\t%s\n", + username, useruid, + queue->sender, + queue->id, + hostname(), VERSION, + rfc822date()); + if ((ssize_t)error < 0) + return (-1); + + while (!feof(stdin)) { + if (fgets(line, sizeof(line) - 1, stdin) == NULL) + break; + if (had_last_line) + errlogx(EX_DATAERR, "bad mail input format:" + " from %s (uid %d) (envelope-from %s)", + username, useruid, queue->sender); + linelen = strlen(line); + if (linelen == 0 || line[linelen - 1] != '\n') { + /* + * This line did not end with a newline character. + * If we fix it, it better be the last line of + * the file. + */ + line[linelen] = '\n'; + line[linelen + 1] = 0; + had_last_line = 1; + } + if (!had_headers) { + /* + * Unless this is a continuation, switch of + * the Bcc: nocopy flag. + */ + if (!(line[0] == ' ' || line[0] == '\t')) + nocopy = 0; + + if (strprefixcmp(line, "Date:") == 0) + had_date = 1; + else if (strprefixcmp(line, "Message-Id:") == 0) + had_messagid = 1; + else if (strprefixcmp(line, "From:") == 0) + had_from = 1; + else if (strprefixcmp(line, "Bcc:") == 0) + nocopy = 1; + + if (parse_state.state != NONE) { + if (parse_addrs(&parse_state, line, queue) < 0) { + errlogx(EX_DATAERR, "invalid address in header\n"); + /* NOTREACHED */ + } + } + + if (recp_from_header && ( + strprefixcmp(line, "To:") == 0 || + strprefixcmp(line, "Cc:") == 0 || + strprefixcmp(line, "Bcc:") == 0)) { + parse_state.state = START; + if (parse_addrs(&parse_state, line, queue) < 0) { + errlogx(EX_DATAERR, "invalid address in header\n"); + /* NOTREACHED */ + } + } + } + + if (strcmp(line, "\n") == 0 && !had_headers) { + had_headers = 1; + while (!had_date || !had_messagid || !had_from) { + if (!had_date) { + had_date = 1; + snprintf(line, sizeof(line), "Date: %s\n", rfc822date()); + } else if (!had_messagid) { + /* XXX msgid, assign earlier and log? */ + had_messagid = 1; + snprintf(line, sizeof(line), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n", + (uintmax_t)time(NULL), + queue->id, + (uintmax_t)random(), + hostname()); + } else if (!had_from) { + had_from = 1; + snprintf(line, sizeof(line), "From: <%s>\n", queue->sender); + } + if (fwrite(line, strlen(line), 1, queue->mailf) != 1) + return (-1); + } + strcpy(line, "\n"); + } + if (!nodot && linelen == 2 && line[0] == '.') + break; + if (!nocopy) { + if (fwrite(line, strlen(line), 1, queue->mailf) != 1) + return (-1); + } + } + + return (0); +} Property changes on: vendor/dma/0.10/mail.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/net.c =================================================================== --- vendor/dma/0.10/net.c (nonexistent) +++ vendor/dma/0.10/net.c (revision 289122) @@ -0,0 +1,547 @@ +/* + * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>. + * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthias Schmidt , University of Marburg, + * Germany. + * + * 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 "dfcompat.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dma.h" + +char neterr[ERRMSG_SIZE]; + +char * +ssl_errstr(void) +{ + long oerr, nerr; + + oerr = 0; + while ((nerr = ERR_get_error()) != 0) + oerr = nerr; + + return (ERR_error_string(oerr, NULL)); +} + +ssize_t +send_remote_command(int fd, const char* fmt, ...) +{ + va_list va; + char cmd[4096]; + size_t len, pos; + int s; + ssize_t n; + + va_start(va, fmt); + s = vsnprintf(cmd, sizeof(cmd) - 2, fmt, va); + va_end(va); + if (s == sizeof(cmd) - 2 || s < 0) { + strcpy(neterr, "Internal error: oversized command string"); + return (-1); + } + + /* We *know* there are at least two more bytes available */ + strcat(cmd, "\r\n"); + len = strlen(cmd); + + if (((config.features & SECURETRANS) != 0) && + ((config.features & NOSSL) == 0)) { + while ((s = SSL_write(config.ssl, (const char*)cmd, len)) <= 0) { + s = SSL_get_error(config.ssl, s); + if (s != SSL_ERROR_WANT_READ && + s != SSL_ERROR_WANT_WRITE) { + strncpy(neterr, ssl_errstr(), sizeof(neterr)); + return (-1); + } + } + } + else { + pos = 0; + while (pos < len) { + n = write(fd, cmd + pos, len - pos); + if (n < 0) + return (-1); + pos += n; + } + } + + return (len); +} + +int +read_remote(int fd, int extbufsize, char *extbuf) +{ + ssize_t rlen = 0; + size_t pos, len, copysize; + char buff[BUF_SIZE]; + int done = 0, status = 0, status_running = 0, extbufpos = 0; + enum { parse_status, parse_spacedash, parse_rest } parsestate; + + if (do_timeout(CON_TIMEOUT, 1) != 0) { + snprintf(neterr, sizeof(neterr), "Timeout reached"); + return (-1); + } + + /* + * Remote reading code from femail.c written by Henning Brauer of + * OpenBSD and released under a BSD style license. + */ + len = 0; + pos = 0; + parsestate = parse_status; + neterr[0] = 0; + while (!(done && parsestate == parse_status)) { + rlen = 0; + if (pos == 0 || + (pos > 0 && memchr(buff + pos, '\n', len - pos) == NULL)) { + memmove(buff, buff + pos, len - pos); + len -= pos; + pos = 0; + if (((config.features & SECURETRANS) != 0) && + (config.features & NOSSL) == 0) { + if ((rlen = SSL_read(config.ssl, buff + len, sizeof(buff) - len)) == -1) { + strncpy(neterr, ssl_errstr(), sizeof(neterr)); + goto error; + } + } else { + if ((rlen = read(fd, buff + len, sizeof(buff) - len)) == -1) { + strncpy(neterr, strerror(errno), sizeof(neterr)); + goto error; + } + } + len += rlen; + + copysize = sizeof(neterr) - strlen(neterr) - 1; + if (copysize > len) + copysize = len; + strncat(neterr, buff, copysize); + } + /* + * If there is an external buffer with a size bigger than zero + * and as long as there is space in the external buffer and + * there are new characters read from the mailserver + * copy them to the external buffer + */ + if (extbufpos <= (extbufsize - 1) && rlen > 0 && extbufsize > 0 && extbuf != NULL) { + /* do not write over the bounds of the buffer */ + if(extbufpos + rlen > (extbufsize - 1)) { + rlen = extbufsize - extbufpos; + } + memcpy(extbuf + extbufpos, buff + len - rlen, rlen); + extbufpos += rlen; + } + + if (pos == len) + continue; + + switch (parsestate) { + case parse_status: + for (; pos < len; pos++) { + if (isdigit(buff[pos])) { + status_running = status_running * 10 + (buff[pos] - '0'); + } else { + status = status_running; + status_running = 0; + parsestate = parse_spacedash; + break; + } + } + continue; + + case parse_spacedash: + switch (buff[pos]) { + case ' ': + done = 1; + break; + + case '-': + /* ignore */ + /* XXX read capabilities */ + break; + + default: + strcpy(neterr, "invalid syntax in reply from server"); + goto error; + } + + pos++; + parsestate = parse_rest; + continue; + + case parse_rest: + /* skip up to \n */ + for (; pos < len; pos++) { + if (buff[pos] == '\n') { + pos++; + parsestate = parse_status; + break; + } + } + } + + } + + do_timeout(0, 0); + + /* chop off trailing newlines */ + while (neterr[0] != 0 && strchr("\r\n", neterr[strlen(neterr) - 1]) != 0) + neterr[strlen(neterr) - 1] = 0; + + return (status/100); + +error: + do_timeout(0, 0); + return (-1); +} + +/* + * Handle SMTP authentication + */ +static int +smtp_login(int fd, char *login, char* password) +{ + char *temp; + int len, res = 0; + + res = smtp_auth_md5(fd, login, password); + if (res == 0) { + return (0); + } else if (res == -2) { + /* + * If the return code is -2, then then the login attempt failed, + * do not try other login mechanisms + */ + return (1); + } + + if ((config.features & INSECURE) != 0 || + (config.features & SECURETRANS) != 0) { + /* Send AUTH command according to RFC 2554 */ + send_remote_command(fd, "AUTH LOGIN"); + if (read_remote(fd, 0, NULL) != 3) { + syslog(LOG_NOTICE, "remote delivery deferred:" + " AUTH login not available: %s", + neterr); + return (1); + } + + len = base64_encode(login, strlen(login), &temp); + if (len < 0) { +encerr: + syslog(LOG_ERR, "can not encode auth reply: %m"); + return (1); + } + + send_remote_command(fd, "%s", temp); + free(temp); + res = read_remote(fd, 0, NULL); + if (res != 3) { + syslog(LOG_NOTICE, "remote delivery %s: AUTH login failed: %s", + res == 5 ? "failed" : "deferred", neterr); + return (res == 5 ? -1 : 1); + } + + len = base64_encode(password, strlen(password), &temp); + if (len < 0) + goto encerr; + + send_remote_command(fd, "%s", temp); + free(temp); + res = read_remote(fd, 0, NULL); + if (res != 2) { + syslog(LOG_NOTICE, "remote delivery %s: Authentication failed: %s", + res == 5 ? "failed" : "deferred", neterr); + return (res == 5 ? -1 : 1); + } + } else { + syslog(LOG_WARNING, "non-encrypted SMTP login is disabled in config, so skipping it. "); + return (1); + } + + return (0); +} + +static int +open_connection(struct mx_hostentry *h) +{ + int fd; + + syslog(LOG_INFO, "trying remote delivery to %s [%s] pref %d", + h->host, h->addr, h->pref); + + fd = socket(h->ai.ai_family, h->ai.ai_socktype, h->ai.ai_protocol); + if (fd < 0) { + syslog(LOG_INFO, "socket for %s [%s] failed: %m", + h->host, h->addr); + return (-1); + } + + if (connect(fd, (struct sockaddr *)&h->sa, h->ai.ai_addrlen) < 0) { + syslog(LOG_INFO, "connect to %s [%s] failed: %m", + h->host, h->addr); + close(fd); + return (-1); + } + + return (fd); +} + +static void +close_connection(int fd) +{ + if (config.ssl != NULL) { + if (((config.features & SECURETRANS) != 0) && + ((config.features & NOSSL) == 0)) + SSL_shutdown(config.ssl); + SSL_free(config.ssl); + } + + close(fd); +} + +static int +deliver_to_host(struct qitem *it, struct mx_hostentry *host) +{ + struct authuser *a; + char line[1000]; + size_t linelen; + int fd, error = 0, do_auth = 0, res = 0; + + if (fseek(it->mailf, 0, SEEK_SET) != 0) { + snprintf(errmsg, sizeof(errmsg), "can not seek: %s", strerror(errno)); + return (-1); + } + + fd = open_connection(host); + if (fd < 0) + return (1); + +#define READ_REMOTE_CHECK(c, exp) \ + res = read_remote(fd, 0, NULL); \ + if (res == 5) { \ + syslog(LOG_ERR, "remote delivery to %s [%s] failed after %s: %s", \ + host->host, host->addr, c, neterr); \ + snprintf(errmsg, sizeof(errmsg), "%s [%s] did not like our %s:\n%s", \ + host->host, host->addr, c, neterr); \ + return (-1); \ + } else if (res != exp) { \ + syslog(LOG_NOTICE, "remote delivery deferred: %s [%s] failed after %s: %s", \ + host->host, host->addr, c, neterr); \ + return (1); \ + } + + /* Check first reply from remote host */ + if ((config.features & SECURETRANS) == 0 || + (config.features & STARTTLS) != 0) { + config.features |= NOSSL; + READ_REMOTE_CHECK("connect", 2); + + config.features &= ~NOSSL; + } + + if ((config.features & SECURETRANS) != 0) { + error = smtp_init_crypto(fd, config.features); + if (error == 0) + syslog(LOG_DEBUG, "SSL initialization successful"); + else + goto out; + + if ((config.features & STARTTLS) == 0) + READ_REMOTE_CHECK("connect", 2); + } + + /* XXX allow HELO fallback */ + /* XXX record ESMTP keywords */ + send_remote_command(fd, "EHLO %s", hostname()); + READ_REMOTE_CHECK("EHLO", 2); + + /* + * Use SMTP authentication if the user defined an entry for the remote + * or smarthost + */ + SLIST_FOREACH(a, &authusers, next) { + if (strcmp(a->host, host->host) == 0) { + do_auth = 1; + break; + } + } + + if (do_auth == 1) { + /* + * Check if the user wants plain text login without using + * encryption. + */ + syslog(LOG_INFO, "using SMTP authentication for user %s", a->login); + error = smtp_login(fd, a->login, a->password); + if (error < 0) { + syslog(LOG_ERR, "remote delivery failed:" + " SMTP login failed: %m"); + snprintf(errmsg, sizeof(errmsg), "SMTP login to %s failed", host->host); + return (-1); + } + /* SMTP login is not available, so try without */ + else if (error > 0) { + syslog(LOG_WARNING, "SMTP login not available. Trying without."); + } + } + + /* XXX send ESMTP ENVID, RET (FULL/HDRS) and 8BITMIME */ + send_remote_command(fd, "MAIL FROM:<%s>", it->sender); + READ_REMOTE_CHECK("MAIL FROM", 2); + + /* XXX send ESMTP ORCPT */ + send_remote_command(fd, "RCPT TO:<%s>", it->addr); + READ_REMOTE_CHECK("RCPT TO", 2); + + send_remote_command(fd, "DATA"); + READ_REMOTE_CHECK("DATA", 3); + + error = 0; + while (!feof(it->mailf)) { + if (fgets(line, sizeof(line), it->mailf) == NULL) + break; + linelen = strlen(line); + if (linelen == 0 || line[linelen - 1] != '\n') { + syslog(LOG_CRIT, "remote delivery failed: corrupted queue file"); + snprintf(errmsg, sizeof(errmsg), "corrupted queue file"); + error = -1; + goto out; + } + + /* Remove trailing \n's and escape leading dots */ + trim_line(line); + + /* + * If the first character is a dot, we escape it so the line + * length increases + */ + if (line[0] == '.') + linelen++; + + if (send_remote_command(fd, "%s", line) != (ssize_t)linelen+1) { + syslog(LOG_NOTICE, "remote delivery deferred: write error"); + error = 1; + goto out; + } + } + + send_remote_command(fd, "."); + READ_REMOTE_CHECK("final DATA", 2); + + send_remote_command(fd, "QUIT"); + if (read_remote(fd, 0, NULL) != 2) + syslog(LOG_INFO, "remote delivery succeeded but QUIT failed: %s", neterr); +out: + + close_connection(fd); + return (error); +} + +int +deliver_remote(struct qitem *it) +{ + struct mx_hostentry *hosts, *h; + const char *host; + int port; + int error = 1, smarthost = 0; + + port = SMTP_PORT; + + /* Smarthost support? */ + if (config.smarthost != NULL) { + host = config.smarthost; + port = config.port; + syslog(LOG_INFO, "using smarthost (%s:%i)", host, port); + smarthost = 1; + } else { + host = strrchr(it->addr, '@'); + /* Should not happen */ + if (host == NULL) { + snprintf(errmsg, sizeof(errmsg), "Internal error: badly formed address %s", + it->addr); + return(-1); + } else { + /* Step over the @ */ + host++; + } + } + + error = dns_get_mx_list(host, port, &hosts, smarthost); + if (error) { + snprintf(errmsg, sizeof(errmsg), "DNS lookup failure: host %s not found", host); + syslog(LOG_NOTICE, "remote delivery %s: DNS lookup failure: host %s not found", + error < 0 ? "failed" : "deferred", + host); + return (error); + } + + for (h = hosts; *h->host != 0; h++) { + switch (deliver_to_host(it, h)) { + case 0: + /* success */ + error = 0; + goto out; + case 1: + /* temp failure */ + error = 1; + break; + default: + /* perm failure */ + error = -1; + goto out; + } + } +out: + free(hosts); + + return (error); +} Property changes on: vendor/dma/0.10/net.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/spool.c =================================================================== --- vendor/dma/0.10/spool.c (nonexistent) +++ vendor/dma/0.10/spool.c (revision 289122) @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>. + * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Simon Schubert <2@0x2c.org>. + * + * 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 "dfcompat.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dma.h" + +/* + * Spool file format: + * + * 'Q'id files (queue): + * Organized like an RFC822 header, field: value. Ignores unknown fields. + * ID: id + * Sender: envelope-from + * Recipient: envelope-to + * + * 'M'id files (data): + * mail data + * + * Each queue file needs to have a corresponding data file. + * One data file might be shared by linking it several times. + * + * Queue ids are unique, formed from the inode of the data file + * and a unique identifier. + */ + +int +newspoolf(struct queue *queue) +{ + char fn[PATH_MAX+1]; + struct stat st; + struct stritem *t; + int fd; + + if (snprintf(fn, sizeof(fn), "%s/%s", config.spooldir, "tmp_XXXXXXXXXX") <= 0) + return (-1); + + fd = mkstemp(fn); + if (fd < 0) + return (-1); + /* XXX group rights */ + if (fchmod(fd, 0660) < 0) + goto fail; + if (flock(fd, LOCK_EX) == -1) + goto fail; + queue->tmpf = strdup(fn); + if (queue->tmpf == NULL) + goto fail; + + /* + * Assign queue id + */ + if (fstat(fd, &st) != 0) + goto fail; + if (asprintf(&queue->id, "%"PRIxMAX, (uintmax_t)st.st_ino) < 0) + goto fail; + + queue->mailf = fdopen(fd, "r+"); + if (queue->mailf == NULL) + goto fail; + + t = malloc(sizeof(*t)); + if (t != NULL) { + t->str = queue->tmpf; + SLIST_INSERT_HEAD(&tmpfs, t, next); + } + return (0); + +fail: + if (queue->mailf != NULL) + fclose(queue->mailf); + close(fd); + unlink(fn); + return (-1); +} + +static int +writequeuef(struct qitem *it) +{ + int error; + int queuefd; + + queuefd = open_locked(it->queuefn, O_CREAT|O_EXCL|O_RDWR, 0660); + if (queuefd == -1) + return (-1); + if (fchmod(queuefd, 0660) < 0) + return (-1); + it->queuef = fdopen(queuefd, "w+"); + if (it->queuef == NULL) + return (-1); + + error = fprintf(it->queuef, + "ID: %s\n" + "Sender: %s\n" + "Recipient: %s\n", + it->queueid, + it->sender, + it->addr); + + if (error <= 0) + return (-1); + + if (fflush(it->queuef) != 0 || fsync(fileno(it->queuef)) != 0) + return (-1); + + return (0); +} + +static struct qitem * +readqueuef(struct queue *queue, char *queuefn) +{ + char line[1000]; + struct queue itmqueue; + FILE *queuef = NULL; + char *s; + char *queueid = NULL, *sender = NULL, *addr = NULL; + struct qitem *it = NULL; + + bzero(&itmqueue, sizeof(itmqueue)); + LIST_INIT(&itmqueue.queue); + + queuef = fopen(queuefn, "r"); + if (queuef == NULL) + goto out; + + while (!feof(queuef)) { + if (fgets(line, sizeof(line), queuef) == NULL || line[0] == 0) + break; + line[strlen(line) - 1] = 0; /* chop newline */ + + s = strchr(line, ':'); + if (s == NULL) + goto malformed; + *s = 0; + + s++; + while (isspace(*s)) + s++; + + s = strdup(s); + if (s == NULL) + goto malformed; + + if (strcmp(line, "ID") == 0) { + queueid = s; + } else if (strcmp(line, "Sender") == 0) { + sender = s; + } else if (strcmp(line, "Recipient") == 0) { + addr = s; + } else { + syslog(LOG_DEBUG, "ignoring unknown queue info `%s' in `%s'", + line, queuefn); + free(s); + } + } + + if (queueid == NULL || sender == NULL || addr == NULL || + *queueid == 0 || *addr == 0) { +malformed: + errno = EINVAL; + syslog(LOG_ERR, "malformed queue file `%s'", queuefn); + goto out; + } + + if (add_recp(&itmqueue, addr, 0) != 0) + goto out; + + it = LIST_FIRST(&itmqueue.queue); + it->sender = sender; sender = NULL; + it->queueid = queueid; queueid = NULL; + it->queuefn = queuefn; queuefn = NULL; + LIST_INSERT_HEAD(&queue->queue, it, next); + +out: + if (sender != NULL) + free(sender); + if (queueid != NULL) + free(queueid); + if (addr != NULL) + free(addr); + if (queuef != NULL) + fclose(queuef); + + return (it); +} + +int +linkspool(struct queue *queue) +{ + struct stat st; + struct qitem *it; + + if (fflush(queue->mailf) != 0 || fsync(fileno(queue->mailf)) != 0) + goto delfiles; + + syslog(LOG_INFO, "new mail from user=%s uid=%d envelope_from=<%s>", + username, getuid(), queue->sender); + + LIST_FOREACH(it, &queue->queue, next) { + if (asprintf(&it->queueid, "%s.%"PRIxPTR, queue->id, (uintptr_t)it) <= 0) + goto delfiles; + if (asprintf(&it->queuefn, "%s/Q%s", config.spooldir, it->queueid) <= 0) + goto delfiles; + if (asprintf(&it->mailfn, "%s/M%s", config.spooldir, it->queueid) <= 0) + goto delfiles; + + /* Neither file may not exist yet */ + if (stat(it->queuefn, &st) == 0 || stat(it->mailfn, &st) == 0) + goto delfiles; + + if (writequeuef(it) != 0) + goto delfiles; + + if (link(queue->tmpf, it->mailfn) != 0) + goto delfiles; + } + + LIST_FOREACH(it, &queue->queue, next) { + syslog(LOG_INFO, "mail to=<%s> queued as %s", + it->addr, it->queueid); + } + + unlink(queue->tmpf); + return (0); + +delfiles: + LIST_FOREACH(it, &queue->queue, next) { + unlink(it->mailfn); + unlink(it->queuefn); + } + return (-1); +} + +int +load_queue(struct queue *queue) +{ + struct stat sb; + struct qitem *it; + DIR *spooldir; + struct dirent *de; + char *queuefn; + char *mailfn; + + bzero(queue, sizeof(*queue)); + LIST_INIT(&queue->queue); + + spooldir = opendir(config.spooldir); + if (spooldir == NULL) + err(EX_NOINPUT, "reading queue"); + + while ((de = readdir(spooldir)) != NULL) { + queuefn = NULL; + mailfn = NULL; + + /* ignore non-queue files */ + if (de->d_name[0] != 'Q') + continue; + if (asprintf(&queuefn, "%s/Q%s", config.spooldir, de->d_name + 1) < 0) + goto fail; + if (asprintf(&mailfn, "%s/M%s", config.spooldir, de->d_name + 1) < 0) + goto fail; + + /* + * Some file systems don't provide a de->d_type, so we have to + * do an explicit stat on the queue file. + * Move on if it turns out to be something else than a file. + */ + if (stat(queuefn, &sb) != 0) + goto skip_item; + if (!S_ISREG(sb.st_mode)) { + errno = EINVAL; + goto skip_item; + } + + if (stat(mailfn, &sb) != 0) + goto skip_item; + + it = readqueuef(queue, queuefn); + if (it == NULL) + goto skip_item; + + it->mailfn = mailfn; + continue; + +skip_item: + syslog(LOG_INFO, "could not pick up queue file: `%s'/`%s': %m", queuefn, mailfn); + if (queuefn != NULL) + free(queuefn); + if (mailfn != NULL) + free(mailfn); + } + closedir(spooldir); + return (0); + +fail: + return (-1); +} + +void +delqueue(struct qitem *it) +{ + unlink(it->mailfn); + unlink(it->queuefn); + if (it->queuef != NULL) + fclose(it->queuef); + if (it->mailf != NULL) + fclose(it->mailf); + free(it); +} + +int +acquirespool(struct qitem *it) +{ + int queuefd; + + if (it->queuef == NULL) { + queuefd = open_locked(it->queuefn, O_RDWR|O_NONBLOCK); + if (queuefd < 0) + goto fail; + it->queuef = fdopen(queuefd, "r+"); + if (it->queuef == NULL) + goto fail; + } + + if (it->mailf == NULL) { + it->mailf = fopen(it->mailfn, "r"); + if (it->mailf == NULL) + goto fail; + } + + return (0); + +fail: + if (errno == EWOULDBLOCK) + return (1); + syslog(LOG_INFO, "could not acquire queue file: %m"); + return (-1); +} + +void +dropspool(struct queue *queue, struct qitem *keep) +{ + struct qitem *it; + + LIST_FOREACH(it, &queue->queue, next) { + if (it == keep) + continue; + + if (it->queuef != NULL) + fclose(it->queuef); + if (it->mailf != NULL) + fclose(it->mailf); + } +} + +int +flushqueue_since(unsigned int period) +{ + struct stat st; + struct timeval now; + char *flushfn = NULL; + + if (asprintf(&flushfn, "%s/%s", config.spooldir, SPOOL_FLUSHFILE) < 0) + return (0); + if (stat(flushfn, &st) < 0) { + free(flushfn); + return (0); + } + free(flushfn); + flushfn = NULL; + if (gettimeofday(&now, 0) != 0) + return (0); + + /* Did the flush file get touched within the last period seconds? */ + if (st.st_mtim.tv_sec + period >= now.tv_sec) + return (1); + else + return (0); +} + +int +flushqueue_signal(void) +{ + char *flushfn = NULL; + int fd; + + if (asprintf(&flushfn, "%s/%s", config.spooldir, SPOOL_FLUSHFILE) < 0) + return (-1); + fd = open(flushfn, O_CREAT|O_WRONLY|O_TRUNC, 0660); + free(flushfn); + if (fd < 0) { + syslog(LOG_ERR, "could not open flush file: %m"); + return (-1); + } + close(fd); + return (0); +} Property changes on: vendor/dma/0.10/spool.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/util.c =================================================================== --- vendor/dma/0.10/util.c (nonexistent) +++ vendor/dma/0.10/util.c (revision 289122) @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>. + * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Simon Schubert <2@0x2c.org>. + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dma.h" + +const char * +hostname(void) +{ +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 255 +#endif + static char name[HOST_NAME_MAX+1]; + static int initialized = 0; + char *s; + + if (initialized) + return (name); + + if (config.mailname == NULL || !*config.mailname) + goto local; + + if (config.mailname[0] == '/') { + /* + * If the mailname looks like an absolute path, + * treat it as a file. + */ + FILE *fp; + + fp = fopen(config.mailname, "r"); + if (fp == NULL) + goto local; + + s = fgets(name, sizeof(name), fp); + fclose(fp); + if (s == NULL) + goto local; + + for (s = name; *s != 0 && (isalnum(*s) || strchr("_.-", *s)); ++s) + /* NOTHING */; + *s = 0; + + if (!*name) + goto local; + + initialized = 1; + return (name); + } else { + snprintf(name, sizeof(name), "%s", config.mailname); + initialized = 1; + return (name); + } + +local: + if (gethostname(name, sizeof(name)) != 0) + *name = 0; + /* + * gethostname() is allowed to truncate name without NUL-termination + * and at the same time not return an error. + */ + name[sizeof(name) - 1] = 0; + + for (s = name; *s != 0 && (isalnum(*s) || strchr("_.-", *s)); ++s) + /* NOTHING */; + *s = 0; + + if (!*name) + snprintf(name, sizeof(name), "unknown-hostname"); + + initialized = 1; + return (name); +} + +void +setlogident(const char *fmt, ...) +{ + static char tag[50]; + + snprintf(tag, sizeof(tag), "%s", logident_base); + if (fmt != NULL) { + va_list ap; + char sufx[50]; + + va_start(ap, fmt); + vsnprintf(sufx, sizeof(sufx), fmt, ap); + va_end(ap); + snprintf(tag, sizeof(tag), "%s[%s]", logident_base, sufx); + } + closelog(); + openlog(tag, 0, LOG_MAIL); +} + +void +errlog(int exitcode, const char *fmt, ...) +{ + int oerrno = errno; + va_list ap; + char outs[ERRMSG_SIZE]; + + outs[0] = 0; + if (fmt != NULL) { + va_start(ap, fmt); + vsnprintf(outs, sizeof(outs), fmt, ap); + va_end(ap); + } + + errno = oerrno; + if (*outs != 0) { + 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[ERRMSG_SIZE]; + + outs[0] = 0; + if (fmt != NULL) { + va_start(ap, fmt); + vsnprintf(outs, sizeof(outs), fmt, ap); + va_end(ap); + } + + if (*outs != 0) { + 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 int +check_username(const char *name, uid_t ckuid) +{ + struct passwd *pwd; + + if (name == NULL) + return (0); + pwd = getpwnam(name); + if (pwd == NULL || pwd->pw_uid != ckuid) + return (0); + snprintf(username, sizeof(username), "%s", name); + return (1); +} + +void +set_username(void) +{ + struct passwd *pwd; + + useruid = getuid(); + if (check_username(getlogin(), useruid)) + return; + if (check_username(getenv("LOGNAME"), useruid)) + return; + if (check_username(getenv("USER"), useruid)) + return; + pwd = getpwuid(useruid); + if (pwd != NULL && pwd->pw_name != NULL && pwd->pw_name[0] != '\0') { + if (check_username(pwd->pw_name, useruid)) + return; + } + snprintf(username, sizeof(username), "uid=%ld", (long)useruid); +} + +void +deltmp(void) +{ + struct stritem *t; + + SLIST_FOREACH(t, &tmpfs, next) { + unlink(t->str); + } +} + +static sigjmp_buf sigbuf; +static int sigbuf_valid; + +static void +sigalrm_handler(int signo) +{ + (void)signo; /* so that gcc doesn't complain */ + if (sigbuf_valid) + siglongjmp(sigbuf, 1); +} + +int +do_timeout(int timeout, int dojmp) +{ + struct sigaction act; + int ret = 0; + + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + + if (timeout) { + act.sa_handler = sigalrm_handler; + if (sigaction(SIGALRM, &act, NULL) != 0) + syslog(LOG_WARNING, "can not set signal handler: %m"); + if (dojmp) { + ret = sigsetjmp(sigbuf, 1); + if (ret) + goto disable; + /* else just programmed */ + sigbuf_valid = 1; + } + + alarm(timeout); + } else { +disable: + alarm(0); + + act.sa_handler = SIG_IGN; + if (sigaction(SIGALRM, &act, NULL) != 0) + syslog(LOG_WARNING, "can not remove signal handler: %m"); + sigbuf_valid = 0; + } + + return (ret); +} + +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))); +} + +void +init_random(void) +{ + unsigned int seed; + int rf; + + rf = open("/dev/urandom", O_RDONLY); + if (rf == -1) + rf = open("/dev/random", O_RDONLY); + + if (!(rf != -1 && read(rf, &seed, sizeof(seed)) == sizeof(seed))) + seed = (time(NULL) ^ getpid()) + (uintptr_t)&seed; + + srandom(seed); + + if (rf != -1) + close(rf); +} Property changes on: vendor/dma/0.10/util.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/INSTALL =================================================================== --- vendor/dma/0.10/INSTALL (nonexistent) +++ vendor/dma/0.10/INSTALL (revision 289122) @@ -0,0 +1,28 @@ +Installing DMA: +=============== + +On most systems (with a development environment installed) you should be able to compile DMA with: + make + +Once it have compiled it successfully, you can install it with: + make install sendmail-link mailq-link install-spool-dirs install-etc + +Troubleshooting: +---------------- +On systems that do not default to a compatible "make" version, try using "gmake" or "pmake" instead of "make". Some known examples of this: +* Solaris 9 +* Solaris 10 + +Check that you have the following commands installed: +* cc - gcc is known to work +* lex - flex is known to work +* yacc - bison is kjnown to work +* make - BSD make and GNU make is knwon to work +* sh - Need to be POSIX compliant, dash, bash known to work +* install - GNU and BSD versions known to work +* openssl - Add the header location to C_INCLUDE_PATH if you get errors about "err.h" + +If you have all of these tools installed, set the CC, YACC, INSTALL, LEX and SH variable to point to the relevant location and command. + +Example: + make CC=gcc YACC=bison LEX=/usr/bin/flex SH=/bin/bash INSTALL=/usr/bin/install Index: vendor/dma/0.10/Makefile =================================================================== --- vendor/dma/0.10/Makefile (nonexistent) +++ vendor/dma/0.10/Makefile (revision 289122) @@ -0,0 +1,111 @@ +# +# Depending on your operating system, you might want to influence +# the conditional inclusion of some helper functions: +# +# Define HAVE_* (in caps) if your system already provides: +# reallocf +# strlcpy +# getprogname +# + +SH?= sh + +version= $(shell ${SH} get-version.sh) +debversion= $(shell ${SH} get-version.sh | sed -Ee 's/^v//;s/[.]([[:digit:]]+)[.](g[[:xdigit:]]+)$$/+\1+\2/') + +CC?= gcc +CFLAGS?= -O -pipe +LDADD?= -lssl -lcrypto -lresolv + +CFLAGS+= -Wall -DDMA_VERSION='"${version}"' -DLIBEXEC_PATH='"${LIBEXEC}"' -DCONF_PATH='"${CONFDIR}"' + +INSTALL?= install -p +CHGRP?= chgrp +CHMOD?= chmod + +PREFIX?= /usr/local +SBIN?= ${PREFIX}/sbin +LIBEXEC?= ${PREFIX}/lib +CONFDIR?= /etc/dma +MAN?= ${PREFIX}/share/man +VAR?= /var +DMASPOOL?= ${VAR}/spool/dma +VARMAIL?= ${VAR}/mail +SYMLINK?= -s # or empty to create hard link + +YACC?= yacc +LEX?= lex +LN?= ln + +OBJS= aliases_parse.o aliases_scan.o base64.o conf.o crypto.o +OBJS+= dma.o dns.o local.o mail.o net.o spool.o util.o +OBJS+= dfcompat.o + +all: dma dma-mbox-create + +clean: + -rm -f .depend dma dma-mbox-create *.[do] + -rm -f aliases_parse.[ch] aliases_scan.c + +install: all + ${INSTALL} -d ${DESTDIR}${SBIN} + ${INSTALL} -d ${DESTDIR}${MAN}/man8 ${DESTDIR}${LIBEXEC} + ${INSTALL} -m 2755 -o root -g mail dma ${DESTDIR}${SBIN} + ${INSTALL} -m 4754 -o root -g mail dma-mbox-create ${DESTDIR}${LIBEXEC} + ${INSTALL} -m 0644 dma.8 ${DESTDIR}${MAN}/man8/ + +sendmail-link: + cd ${DESTDIR}${SBIN} && ${LN} ${SYMLINK} dma sendmail + +mailq-link: + cd ${DESTDIR}${SBIN} && ${LN} ${SYMLINK} dma mailq + +install-spool-dirs: + ${INSTALL} -d -m 2775 -o root -g mail ${DESTDIR}${DMASPOOL} + ${INSTALL} -d -m 2775 -o root -g mail ${DESTDIR}${VARMAIL} + +permissions: + -${CHGRP} mail ${DESTDIR}${VARMAIL}/* + -${CHMOD} g+w ${DESTDIR}${VARMAIL}/* + -${CHMOD} 660 ${DESTDIR}${DMASPOOL}/flush + +install-etc: + ${INSTALL} -d ${DESTDIR}${CONFDIR} + @if [ -e ${DESTDIR}${CONFDIR}/dma.conf ]; then \ + echo "Not overwriting ${DESTDIR}${CONFDIR}/dma.conf."; \ + else \ + echo ${INSTALL} -m 644 -o root -g mail dma.conf ${DESTDIR}${CONFDIR}; \ + ${INSTALL} -m 644 -o root -g mail dma.conf ${DESTDIR}${CONFDIR}; \ + fi + @if [ -e ${DESTDIR}${CONFDIR}/auth.conf ]; then \ + echo "Not overwriting ${DESTDIR}${CONFDIR}/auth.conf."; \ + else \ + echo ${INSTALL} -m 640 -o root -g mail auth.conf ${DESTDIR}${CONFDIR}; \ + ${INSTALL} -m 640 -o root -g mail auth.conf ${DESTDIR}${CONFDIR}; \ + fi + +aliases_parse.c: aliases_parse.y + ${YACC} -d -o aliases_parse.c aliases_parse.y + +aliases_scan.c: aliases_scan.l + ${LEX} -t aliases_scan.l > aliases_scan.c + +.SUFFIXES: .c .o + +.c.o: + ${CC} ${CFLAGS} ${CPPFLAGS} -include dfcompat.h -o $@ -c $< + +dma: ${OBJS} + ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LDADD} + + +dch: + dch --release-heuristic changelog -v ${debversion} + + +ppa: + @if [ -z '${DEB_DIST}' ]; then echo "please set DEB_DIST to build"; exit 1; fi + dch -v "${debversion}~${DEB_DIST}" -D ${DEB_DIST} "${DEB_DIST} build" -b + debuild -S -sa + ver=$$(dpkg-parsechangelog -n1 | awk '$$1 == "Version:" { print $$2 }'); \ + dput ppa:corecode/dma ../dma_$${ver}_source.changes Property changes on: vendor/dma/0.10/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/Makefile.etc =================================================================== --- vendor/dma/0.10/Makefile.etc (nonexistent) +++ vendor/dma/0.10/Makefile.etc (revision 289122) @@ -0,0 +1,15 @@ +# $DragonFly: src/etc/dma/Makefile,v 1.3 2008/02/12 22:10:20 matthias Exp $ + +FILESDIR= /etc/dma +SHAREOWN= root +SHAREGRP= mail +FILESMODE= 640 + +.if !exists(${DESTDIR}/etc/dma/auth.conf) +FILES+= auth.conf +.endif +.if !exists(${DESTDIR}/etc/dma/dma.conf) +FILES+= dma.conf +.endif + +.include Property changes on: vendor/dma/0.10/Makefile.etc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/auth.conf =================================================================== --- vendor/dma/0.10/auth.conf (nonexistent) +++ vendor/dma/0.10/auth.conf (revision 289122) @@ -0,0 +1,4 @@ +# $DragonFly: src/etc/dma/auth.conf,v 1.1 2008/02/02 18:24:00 matthias Exp $ +# +# SMTP authentication entries (currently AUTH LOGIN only) +# Format: user|my.smarthost.example.com:password Property changes on: vendor/dma/0.10/auth.conf ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/base64.c =================================================================== --- vendor/dma/0.10/base64.c (nonexistent) +++ vendor/dma/0.10/base64.c (revision 289122) @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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 +#include + +#include "dma.h" + +static char base64_chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static int +pos(char c) +{ + char *p; + for (p = base64_chars; *p; p++) + if (*p == c) + return p - base64_chars; + return -1; +} + + +int +base64_encode(const void *data, int size, char **str) +{ + char *s, *p; + int i; + int c; + const unsigned char *q; + + p = s = (char *) malloc(size * 4 / 3 + 4); + if (p == NULL) + return -1; + q = (const unsigned char *) data; + i = 0; + for (i = 0; i < size;) { + c = q[i++]; + c *= 256; + if (i < size) + c += q[i]; + i++; + c *= 256; + if (i < size) + c += q[i]; + i++; + p[0] = base64_chars[(c & 0x00fc0000) >> 18]; + p[1] = base64_chars[(c & 0x0003f000) >> 12]; + p[2] = base64_chars[(c & 0x00000fc0) >> 6]; + p[3] = base64_chars[(c & 0x0000003f) >> 0]; + if (i > size) + p[3] = '='; + if (i > size + 1) + p[2] = '='; + p += 4; + } + *p = 0; + *str = s; + return strlen(s); +} + +#define DECODE_ERROR 0xffffffff + +static unsigned int +token_decode(const char *token) +{ + int i; + unsigned int val = 0; + int marker = 0; + if (strlen(token) < 4) + return DECODE_ERROR; + for (i = 0; i < 4; i++) { + val *= 64; + if (token[i] == '=') + marker++; + else if (marker > 0) + return DECODE_ERROR; + else + val += pos(token[i]); + } + if (marker > 2) + return DECODE_ERROR; + return (marker << 24) | val; +} + +int +base64_decode(const char *str, void *data) +{ + const char *p; + unsigned char *q; + + q = data; + for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) { + unsigned int val = token_decode(p); + unsigned int marker = (val >> 24) & 0xff; + if (val == DECODE_ERROR) + return -1; + *q++ = (val >> 16) & 0xff; + if (marker < 2) + *q++ = (val >> 8) & 0xff; + if (marker < 1) + *q++ = val & 0xff; + } + return q - (unsigned char *) data; +} + Property changes on: vendor/dma/0.10/base64.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/crypto.c =================================================================== --- vendor/dma/0.10/crypto.c (nonexistent) +++ vendor/dma/0.10/crypto.c (revision 289122) @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthias Schmidt , University of Marburg, + * Germany. + * + * 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 +#include +#include +#include +#include +#include + +#include + +#include "dma.h" + +static int +init_cert_file(SSL_CTX *ctx, const char *path) +{ + int error; + + /* Load certificate into ctx */ + error = SSL_CTX_use_certificate_chain_file(ctx, path); + if (error < 1) { + syslog(LOG_ERR, "SSL: Cannot load certificate `%s': %s", path, ssl_errstr()); + return (-1); + } + + /* Add private key to ctx */ + error = SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM); + if (error < 1) { + syslog(LOG_ERR, "SSL: Cannot load private key `%s': %s", path, ssl_errstr()); + return (-1); + } + + /* + * Check the consistency of a private key with the corresponding + * certificate + */ + error = SSL_CTX_check_private_key(ctx); + if (error < 1) { + syslog(LOG_ERR, "SSL: Cannot check private key: %s", ssl_errstr()); + return (-1); + } + + return (0); +} + +int +smtp_init_crypto(int fd, int feature) +{ + SSL_CTX *ctx = NULL; +#if (OPENSSL_VERSION_NUMBER >= 0x00909000L) + const SSL_METHOD *meth = NULL; +#else + SSL_METHOD *meth = NULL; +#endif + X509 *cert; + int error; + + /* XXX clean up on error/close */ + /* Init SSL library */ + SSL_library_init(); + SSL_load_error_strings(); + + meth = TLSv1_client_method(); + + ctx = SSL_CTX_new(meth); + if (ctx == NULL) { + syslog(LOG_WARNING, "remote delivery deferred: SSL init failed: %s", ssl_errstr()); + return (1); + } + + /* User supplied a certificate */ + if (config.certfile != NULL) { + error = init_cert_file(ctx, config.certfile); + if (error) { + syslog(LOG_WARNING, "remote delivery deferred"); + return (1); + } + } + + /* + * If the user wants STARTTLS, we have to send EHLO here + */ + if (((feature & SECURETRANS) != 0) && + (feature & STARTTLS) != 0) { + /* TLS init phase, disable SSL_write */ + config.features |= NOSSL; + + send_remote_command(fd, "EHLO %s", hostname()); + if (read_remote(fd, 0, NULL) == 2) { + send_remote_command(fd, "STARTTLS"); + if (read_remote(fd, 0, NULL) != 2) { + if ((feature & TLS_OPP) == 0) { + syslog(LOG_ERR, "remote delivery deferred: STARTTLS not available: %s", neterr); + return (1); + } else { + syslog(LOG_INFO, "in opportunistic TLS mode, STARTTLS not available: %s", neterr); + return (0); + } + } + } + /* End of TLS init phase, enable SSL_write/read */ + config.features &= ~NOSSL; + } + + config.ssl = SSL_new(ctx); + if (config.ssl == NULL) { + syslog(LOG_NOTICE, "remote delivery deferred: SSL struct creation failed: %s", + ssl_errstr()); + return (1); + } + + /* Set ssl to work in client mode */ + SSL_set_connect_state(config.ssl); + + /* Set fd for SSL in/output */ + error = SSL_set_fd(config.ssl, fd); + if (error == 0) { + syslog(LOG_NOTICE, "remote delivery deferred: SSL set fd failed: %s", + ssl_errstr()); + return (1); + } + + /* Open SSL connection */ + error = SSL_connect(config.ssl); + if (error < 0) { + syslog(LOG_ERR, "remote delivery deferred: SSL handshake failed fatally: %s", + ssl_errstr()); + return (1); + } + + /* Get peer certificate */ + cert = SSL_get_peer_certificate(config.ssl); + if (cert == NULL) { + syslog(LOG_WARNING, "remote delivery deferred: Peer did not provide certificate: %s", + ssl_errstr()); + } + X509_free(cert); + + return (0); +} + +/* + * hmac_md5() taken out of RFC 2104. This RFC was written by H. Krawczyk, + * M. Bellare and R. Canetti. + * + * text pointer to data stream + * text_len length of data stream + * key pointer to authentication key + * key_len length of authentication key + * digest caller digest to be filled int + */ +void +hmac_md5(unsigned char *text, int text_len, unsigned char *key, int key_len, + unsigned char* digest) +{ + MD5_CTX context; + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + */ + unsigned char tk[16]; + int i; + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + MD5_CTX tctx; + + MD5_Init(&tctx); + MD5_Update(&tctx, key, key_len); + MD5_Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + bzero( k_ipad, sizeof k_ipad); + bzero( k_opad, sizeof k_opad); + bcopy( key, k_ipad, key_len); + bcopy( key, k_opad, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner MD5 + */ + MD5_Init(&context); /* init context for 1st + * pass */ + MD5_Update(&context, k_ipad, 64); /* start with inner pad */ + MD5_Update(&context, text, text_len); /* then text of datagram */ + MD5_Final(digest, &context); /* finish up 1st pass */ + /* + * perform outer MD5 + */ + MD5_Init(&context); /* init context for 2nd + * pass */ + MD5_Update(&context, k_opad, 64); /* start with outer pad */ + MD5_Update(&context, digest, 16); /* then results of 1st + * hash */ + MD5_Final(digest, &context); /* finish up 2nd pass */ +} + +/* + * CRAM-MD5 authentication + */ +int +smtp_auth_md5(int fd, char *login, char *password) +{ + unsigned char digest[BUF_SIZE]; + char buffer[BUF_SIZE], ascii_digest[33]; + char *temp; + int len, i; + static char hextab[] = "0123456789abcdef"; + + temp = calloc(BUF_SIZE, 1); + memset(buffer, 0, sizeof(buffer)); + memset(digest, 0, sizeof(digest)); + memset(ascii_digest, 0, sizeof(ascii_digest)); + + /* Send AUTH command according to RFC 2554 */ + send_remote_command(fd, "AUTH CRAM-MD5"); + if (read_remote(fd, sizeof(buffer), buffer) != 3) { + syslog(LOG_DEBUG, "smarthost authentication:" + " AUTH cram-md5 not available: %s", neterr); + /* if cram-md5 is not available */ + free(temp); + return (-1); + } + + /* skip 3 char status + 1 char space */ + base64_decode(buffer + 4, temp); + hmac_md5((unsigned char *)temp, strlen(temp), + (unsigned char *)password, strlen(password), digest); + free(temp); + + ascii_digest[32] = 0; + for (i = 0; i < 16; i++) { + ascii_digest[2*i] = hextab[digest[i] >> 4]; + ascii_digest[2*i+1] = hextab[digest[i] & 15]; + } + + /* prepare answer */ + snprintf(buffer, BUF_SIZE, "%s %s", login, ascii_digest); + + /* encode answer */ + len = base64_encode(buffer, strlen(buffer), &temp); + if (len < 0) { + syslog(LOG_ERR, "can not encode auth reply: %m"); + return (-1); + } + + /* send answer */ + send_remote_command(fd, "%s", temp); + free(temp); + if (read_remote(fd, 0, NULL) != 2) { + syslog(LOG_WARNING, "remote delivery deferred:" + " AUTH cram-md5 failed: %s", neterr); + return (-2); + } + + return (0); +} Property changes on: vendor/dma/0.10/crypto.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/dfcompat.c =================================================================== --- vendor/dma/0.10/dfcompat.c (nonexistent) +++ vendor/dma/0.10/dfcompat.c (revision 289122) @@ -0,0 +1,122 @@ +#ifndef HAVE_STRLCPY + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ + * $FreeBSD$ + * $DragonFly: src/lib/libc/string/strlcpy.c,v 1.4 2005/09/18 16:32:34 asmodai Exp $ + */ + +#include "dfcompat.h" + +#include +#include + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} + +#endif /* !HAVE_STRLCPY */ + +#ifndef HAVE_REALLOCF + +/*- + * Copyright (c) 1998, M. Warner Losh + * All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + * $DragonFly: src/lib/libc/stdlib/reallocf.c,v 1.2 2003/06/17 04:26:46 dillon Exp $ + */ +#include + +void * +reallocf(void *ptr, size_t size) +{ + void *nptr; + + nptr = realloc(ptr, size); + if (!nptr && ptr) + free(ptr); + return (nptr); +} + +#endif /* !HAVE_REALLOCF */ + +#ifndef HAVE_GETPROGNAME + +#ifdef __GLIBC__ + +#include + +const char * +getprogname(void) +{ + return (program_invocation_short_name); +} + +#else /* __GLIBC__ */ +#error "no getprogname implementation available" +#endif + +#endif /* !HAVE_GETPROGNAME */ Property changes on: vendor/dma/0.10/dfcompat.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/dfcompat.h =================================================================== --- vendor/dma/0.10/dfcompat.h (nonexistent) +++ vendor/dma/0.10/dfcompat.h (revision 289122) @@ -0,0 +1,24 @@ +#ifndef DFCOMPAT_H +#define DFCOMPAT_H + +#define _GNU_SOURCE + +#include + +#ifndef __DECONST +#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) +#endif + +#ifndef HAVE_STRLCPY +size_t strlcpy(char *, const char *, size_t); +#endif + +#ifndef HAVE_REALLOCF +void *reallocf(void *, size_t); +#endif + +#ifndef HAVE_GETPROGNAME +const char *getprogname(void); +#endif + +#endif /* DFCOMPAT_H */ Property changes on: vendor/dma/0.10/dfcompat.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/dma.conf =================================================================== --- vendor/dma/0.10/dma.conf (nonexistent) +++ vendor/dma/0.10/dma.conf (revision 289122) @@ -0,0 +1,66 @@ +# $DragonFly: src/etc/dma/dma.conf,v 1.2 2008/02/04 10:11:41 matthias Exp $ +# +# Your smarthost (also called relayhost). Leave blank if you don't want +# smarthost support. +# NOTE: on Debian systems this is handled via debconf! +# Please use dpkg-reconfigure dma to change this value. +#SMARTHOST + +# Use this SMTP port. Most users will be fine with the default (25) +#PORT 25 + +# Path to your alias file. Just stay with the default. +#ALIASES /etc/aliases + +# Path to your spooldir. Just stay with the default. +#SPOOLDIR /var/spool/dma + +# SMTP authentication +#AUTHPATH /etc/dma/auth.conf + +# Uncomment if yout want TLS/SSL support +#SECURETRANSFER + +# Uncomment if you want STARTTLS support (only used in combination with +# SECURETRANSFER) +#STARTTLS + +# Uncomment if you have specified STARTTLS above and it should be allowed +# to fail ("opportunistic TLS", use an encrypted connection when available +# but allow an unencrypted one to servers that do not support it) +#OPPORTUNISTIC_TLS + +# Path to your local SSL certificate +#CERTFILE + +# If you want to use plain text SMTP login without using encryption, change +# the SECURE entry below to INSECURE. Otherwise plain login will only work +# over a secure connection. Use this option with caution. +#SECURE + +# Uncomment if you want to defer your mails. This is useful if you are +# behind a dialup line. You have to submit your mails manually with dma -q +#DEFER + +# Uncomment if you want the bounce message to include the complete original +# message, not just the headers. +#FULLBOUNCE + +# The internet hostname dma uses to identify the host. +# If not set or empty, the result of gethostname(2) is used. +# If MAILNAME is an absolute path to a file, the first line of this file +# will be used as the hostname. +#MAILNAME mail.example.net + +# Masquerade envelope from addresses with this address/hostname. +# Use this if mails are not accepted by destination mail servers because +# your sender domain is invalid. +# By default, MASQUERADE is not set. +# Format: MASQUERADE [user@][host] +# Examples: +# MASQUERADE john@ on host "hamlet" will send all mails as john@hamlet +# MASQUERADE percolator will send mails as $username@percolator, e.g. fish@percolator +# MASQUERADE herb@ert will send all mails as herb@ert + +# Directly forward the mail to the SMARTHOST bypassing aliases and local delivery +#NULLCLIENT Property changes on: vendor/dma/0.10/dma.conf ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dma/0.10/test/quote.rfc2822 =================================================================== --- vendor/dma/0.10/test/quote.rfc2822 (nonexistent) +++ vendor/dma/0.10/test/quote.rfc2822 (revision 289122) @@ -0,0 +1,23 @@ +From: test +To: test +Subject: testing! + +From what i can see... + +He came along, +from far away. + +The rabbit comes out +From his rabbit hole. + +Fromtal nudity! + +> From the previous mail + +>From the quote + +From here +From there +>>>From everywhere. + +last line.