-/* Copyright (C) 2002, 2003 Mads Martin Joergensen <mmj at mmj.dk>
- *
- * $Id$
+/*
+ * Copyright (C) 2002, 2003 Mads Martin Joergensen <mmj at mmj.dk>
+ * Copyright (C) 2022 Baptiste Daroussin <bapt@FreeBSD.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
#include "wrappers.h"
#include "log_error.h"
-/* "EHLO \r\n" has length 7 */
-#define EXTRA_EHLO_LEN 7
-int write_ehlo(int sockfd, const char *hostname)
-{
- size_t bytes_written;
-
- bytes_written = dprintf(sockfd, "EHLO %s\r\n", hostname);
+static int
+write_sock(int sockfd, const char *errstr, const char *fmt, ...) {
+ int bytes_written;
+ va_list ap;
+
+ va_start(ap, fmt);
+ bytes_written = vdprintf(sockfd, fmt, ap);
+ va_end(ap);
if(bytes_written < 0) {
- log_error(LOG_ARGS, "Could not write EHLO");
- return errno;
+ log_error(LOG_ARGS, "Could not write %s", errstr);
+ return -1;
}
return 0;
}
-/* "HELO \r\n" has length 7 */
-#define EXTRA_HELO_LEN 7
+
+int write_ehlo(int sockfd, const char *hostname)
+{
+ return (write_sock(sockfd, "EHLO", "EHLO %s\r\n", hostname));
+}
+
int write_helo(int sockfd, const char *hostname)
{
- size_t bytes_written;
-
- bytes_written = dprintf(sockfd, "HELO %s\r\n", hostname);
- if(bytes_written < 0) {
- log_error(LOG_ARGS, "Could not write HELO");
- return errno;
- }
- return 0;
+ return (write_sock(sockfd, "HELO", "HELO %s\r\n", hostname));
}
-/* "MAIL FROM:<> \r\n" has length 15 */
-#define EXTRA_FROM_LEN 15
+
int write_mail_from(int sockfd, const char *from_addr, const char *extra)
{
- size_t bytes_written;
-
if(extra && extra[0] != '\0') {
if(extra[0] == ' ') extra++;
- bytes_written = dprintf(sockfd, "MAIL FROM:<%s> %s\r\n", from_addr,
- extra);
+ return (write_sock(sockfd, "FROM", "MAIL FROM:<%s> %s\r\n",
+ from_addr, extra));
} else
- bytes_written = dprintf(sockfd, "MAIL FROM:<%s>\r\n", from_addr);
- if(bytes_written < 0) {
- log_error(LOG_ARGS, "Could not write FROM");
- return errno;
- }
- return 0;
+ return (write_sock(sockfd, "FROM", "MAIL FROM:<%s>\r\n", from_addr));
}
-/* "RCPT TO:<>\r\n" has length 12 */
-#define EXTRA_RCPT_LEN 12
int write_rcpt_to(int sockfd, const char *rcpt_addr)
{
- size_t bytes_written;
-
- bytes_written = dprintf(sockfd, "RCPT TO:<%s>\r\n", rcpt_addr);
- if(bytes_written < 0) {
- log_error(LOG_ARGS, "Could not write TO");
- return errno;
- }
- return 0;
+ return (write_sock(sockfd, "TO", "RCPT TO:<%s>\r\n", rcpt_addr));
}
{
char *cur, *next;
char newlinebuf[3];
+ size_t len;
int i = 1;
for(next = cur = mapstart; next < mapstart + size; next++) {
if(*next == '\n') {
- if(writen(sockfd, cur, next - cur) < 0) {
+ if(dprintf(sockfd, "%.*s", (int)(next - cur), cur) < 0) {
log_error(LOG_ARGS, "Could not write mail");
return -1;
}
newlinebuf[0] = '\r';
newlinebuf[1] = '\n';
+ len = 2;
if(next < (mapstart + size - 1) && *(next+1) == '.') {
newlinebuf[2] = '.';
+ len++;
}
- if(dprintf(sockfd, "%s", newlinebuf) < 0) {
+ if(dprintf(sockfd, "%.*s", (int)len, newlinebuf) < 0) {
log_error(LOG_ARGS, "Could not write mail");
return -1;
}
int write_dot(int sockfd)
{
- size_t bytes_written;
-
- bytes_written = dprintf(sockfd, "\r\n.\r\n");
- if(bytes_written < 0)
- return errno;
-
- return 0;
-}
-
-/* "\r\n" has length 2 */
-#define EXTRA_CUSTOM_LEN 2
-int write_custom_line(int sockfd, const char *line)
-{
- size_t bytes_written;
-
- bytes_written = dprintf(sockfd, "%s\r\n", line);
- if(bytes_written < 0) {
- log_error(LOG_ARGS, "Could not write customline");
- return errno;
- }
- return 0;
+ return write_sock(sockfd, "", "\r\n.\r\n");
}
-/* "Reply-To: \r\n" has length 12 */
-#define EXTRA_REPLYTO_LEN 12
int write_replyto(int sockfd, const char *replyaddr)
{
- size_t bytes_written;
-
- bytes_written = dprintf(sockfd, "Reply-To: %s\r\n", replyaddr);
- if(bytes_written < 0) {
- log_error(LOG_ARGS, "Could not write Reply-To header");
- return errno;
- }
- return 0;
+ return write_sock(sockfd, "Reply-To header", "Reply-To: %s\r\n", replyaddr);
}
int write_data(int sockfd)
{
- if(write_custom_line(sockfd, "DATA")) {
- log_error(LOG_ARGS, "Could not write DATA");
- return errno;
- }
-
- return 0;
+ return write_sock(sockfd, "DATA", "DATA\r\n");
}
int write_quit(int sockfd)
{
- if(write_custom_line(sockfd, "QUIT")) {
- log_error(LOG_ARGS, "Could not write QUIT");
- return errno;
- }
-
- return 0;
+ return write_sock(sockfd, "QUIT", "QUIT\r\n");
}
int write_rset(int sockfd)
{
- if(write_custom_line(sockfd, "RSET")) {
- log_error(LOG_ARGS, "Could not write RSET");
- return errno;
- }
-
- return 0;
+ return write_sock(sockfd, "RSET", "RSET\r\n");
}
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <sys/mman.h>
#include <atf-c.h>
#include <inttypes.h>
ATF_TC_WITHOUT_HEAD(exec_and_wait);
ATF_TC_WITHOUT_HEAD(find_email_adr);
ATF_TC_WITHOUT_HEAD(strtoim);
+ATF_TC_WITHOUT_HEAD(write_ehlo);
+ATF_TC_WITHOUT_HEAD(write_helo);
+ATF_TC_WITHOUT_HEAD(write_dot);
+ATF_TC_WITHOUT_HEAD(write_data);
+ATF_TC_WITHOUT_HEAD(write_quit);
+ATF_TC_WITHOUT_HEAD(write_rset);
+ATF_TC_WITHOUT_HEAD(write_replyto);
+ATF_TC_WITHOUT_HEAD(write_rcpt_to);
+ATF_TC_WITHOUT_HEAD(write_mail_from);
+ATF_TC_WITHOUT_HEAD(write_mailbody_from_map);
#ifndef NELEM
#define NELEM(array) (sizeof(array) / sizeof((array)[0]))
ATF_REQUIRE_STREQ(errp, "invalid");
}
+ATF_TC_BODY(write_ehlo, tc)
+{
+ ATF_REQUIRE_EQ(write_ehlo(-1, "myname"), -1);
+ int fd = open("ehlo.txt", O_CREAT|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_ehlo(fd, "myname"), 0);
+ close(fd);
+ if (!atf_utils_compare_file("ehlo.txt", "EHLO myname\r\n"))
+ atf_tc_fail("Unexpected output");
+}
+
+ATF_TC_BODY(write_helo, tc)
+{
+ ATF_REQUIRE_EQ(write_helo(-1, "myname"), -1);
+ int fd = open("helo.txt", O_CREAT|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_helo(fd, "myname"), 0);
+ close(fd);
+ if (!atf_utils_compare_file("helo.txt", "HELO myname\r\n"))
+ atf_tc_fail("Unexpected output");
+}
+
+ATF_TC_BODY(write_dot, tc)
+{
+ ATF_REQUIRE_EQ(write_dot(-1), -1);
+ int fd = open("dot.txt", O_CREAT|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_dot(fd), 0);
+ close(fd);
+ if (!atf_utils_compare_file("dot.txt", "\r\n.\r\n"))
+ atf_tc_fail("Unexpected output");
+}
+
+ATF_TC_BODY(write_data, tc)
+{
+ ATF_REQUIRE_EQ(write_data(-1), -1);
+ int fd = open("data.txt", O_CREAT|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_data(fd), 0);
+ close(fd);
+ if (!atf_utils_compare_file("data.txt", "DATA\r\n"))
+ atf_tc_fail("Unexpected output");
+}
+
+ATF_TC_BODY(write_quit, tc)
+{
+ ATF_REQUIRE_EQ(write_quit(-1), -1);
+ int fd = open("quit.txt", O_CREAT|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_quit(fd), 0);
+ close(fd);
+ if (!atf_utils_compare_file("quit.txt", "QUIT\r\n"))
+ atf_tc_fail("Unexpected output");
+}
+
+ATF_TC_BODY(write_rset, tc)
+{
+ ATF_REQUIRE_EQ(write_rset(-1), -1);
+ int fd = open("rset.txt", O_CREAT|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_rset(fd), 0);
+ close(fd);
+ if (!atf_utils_compare_file("rset.txt", "RSET\r\n"))
+ atf_tc_fail("Unexpected output");
+}
+
+ATF_TC_BODY(write_replyto, tc)
+{
+ ATF_REQUIRE_EQ(write_replyto(-1, "toto"), -1);
+ int fd = open("replyto.txt", O_CREAT|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_replyto(fd, "toto"), 0);
+ close(fd);
+ if (!atf_utils_compare_file("replyto.txt", "Reply-To: toto\r\n"))
+ atf_tc_fail("Unexpected output");
+}
+
+ATF_TC_BODY(write_rcpt_to, tc)
+{
+ ATF_REQUIRE_EQ(write_rcpt_to(-1, "toto"), -1);
+ int fd = open("rcpt_to.txt", O_CREAT|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_rcpt_to(fd, "toto"), 0);
+ close(fd);
+ if (!atf_utils_compare_file("rcpt_to.txt", "RCPT TO:<toto>\r\n")) {
+ atf_utils_cat_file("rcpt_to.txt", "");
+ atf_tc_fail("Unexpected output");
+ }
+}
+
+ATF_TC_BODY(write_mail_from, tc)
+{
+ ATF_REQUIRE_EQ(write_mail_from(-1, "toto", NULL), -1);
+ int fd = open("mail_from.txt", O_CREAT|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_mail_from(fd, "toto", NULL), 0);
+ close(fd);
+ if (!atf_utils_compare_file("mail_from.txt", "MAIL FROM:<toto>\r\n")) {
+ atf_utils_cat_file("mail_from.txt", "");
+ atf_tc_fail("Unexpected output");
+ }
+ fd = open("mail_from.txt", O_CREAT|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_mail_from(fd, "toto", "meh"), 0);
+ close(fd);
+ if (!atf_utils_compare_file("mail_from.txt", "MAIL FROM:<toto> meh\r\n")) {
+ atf_utils_cat_file("mail_from.txt", "");
+ atf_tc_fail("Unexpected output");
+ }
+ fd = open("mail_from.txt", O_CREAT|O_WRONLY|O_TRUNC, 0644);
+ ATF_REQUIRE_EQ(write_mail_from(fd, "toto", ""), 0);
+ close(fd);
+ if (!atf_utils_compare_file("mail_from.txt", "MAIL FROM:<toto>\r\n")) {
+ atf_utils_cat_file("mail_from.txt", "");
+ atf_tc_fail("Unexpected output");
+ }
+ fd = open("mail_from.txt", O_CREAT|O_WRONLY|O_TRUNC, 0644);
+ ATF_REQUIRE_EQ(write_mail_from(fd, "toto", " "), 0);
+ close(fd);
+ if (!atf_utils_compare_file("mail_from.txt", "MAIL FROM:<toto> \r\n")) {
+ atf_utils_cat_file("mail_from.txt", "");
+ atf_tc_fail("Unexpected output");
+ }
+}
+
+ATF_TC_BODY(write_mailbody_from_map, tc)
+{
+ /* no new lines: ignore */
+ struct stat st;
+ char *start;
+ FILE *f = fopen("myemailbody.txt", "w");
+ fprintf(f, "line");
+ fclose(f);
+ int fd1 = open("myemailbody.txt", O_RDONLY);
+ fstat(fd1, &st);
+ ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
+ int fd = open("out.txt", O_CREAT|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_mailbody_from_map(fd, start, st.st_size, "test@plop.meh"), 0);
+ close(fd);
+ munmap(start, st.st_size);
+ close(fd1);
+ if (!atf_utils_compare_file("out.txt", "")) {
+ atf_utils_cat_file("out.txt", ">");
+ atf_tc_fail("Unexpected output");
+ }
+
+ /* With a single new line */
+ f = fopen("myemailbody.txt", "w");
+ fprintf(f, "line\n");
+ fclose(f);
+ fd1 = open("myemailbody.txt", O_RDONLY);
+ fstat(fd1, &st);
+ ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
+ fd = open("out.txt", O_CREAT|O_TRUNC|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_mailbody_from_map(fd, start, st.st_size, "test@plop.meh"), 0);
+ close(fd);
+ munmap(start, st.st_size);
+ close(fd1);
+ if (!atf_utils_compare_file("out.txt", "line\r\n")) {
+ atf_utils_cat_file("out.txt", ">");
+ atf_tc_fail("Unexpected output");
+ }
+
+ /* With a single new line with a . */
+ f = fopen("myemailbody.txt", "w");
+ fprintf(f, "line\n.");
+ fclose(f);
+ fd1 = open("myemailbody.txt", O_RDONLY);
+ fstat(fd1, &st);
+ ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
+ fd = open("out.txt", O_CREAT|O_TRUNC|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_mailbody_from_map(fd, start, st.st_size, "test@plop.meh"), 0);
+ close(fd);
+ munmap(start, st.st_size);
+ close(fd1);
+ if (!atf_utils_compare_file("out.txt", "line\r\n.")) {
+ atf_utils_cat_file("out.txt", ">");
+ atf_tc_fail("Unexpected output");
+ }
+
+ /* With a single new line, 2 new lines */
+ f = fopen("myemailbody.txt", "w");
+ fprintf(f, "line\n\n");
+ fclose(f);
+ fd1 = open("myemailbody.txt", O_RDONLY);
+ fstat(fd1, &st);
+ ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
+ fd = open("out.txt", O_CREAT|O_TRUNC|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_mailbody_from_map(fd, start, st.st_size, "test@plop.meh"), 0);
+ close(fd);
+ munmap(start, st.st_size);
+ close(fd1);
+ if (!atf_utils_compare_file("out.txt", "line\r\ntest@plop.meh\r\n")) {
+ atf_utils_cat_file("out.txt", ">");
+ atf_tc_fail("Unexpected output");
+ }
+
+
+ /* With a single 2 lines separated by 2 new lines*/
+ f = fopen("myemailbody.txt", "w");
+ fprintf(f, "line\n\nline2\n\n");
+ fclose(f);
+ fd1 = open("myemailbody.txt", O_RDONLY);
+ fstat(fd1, &st);
+ ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
+ fd = open("out.txt", O_CREAT|O_TRUNC|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_mailbody_from_map(fd, start, st.st_size, "test@plop.meh"), 0);
+ close(fd);
+ munmap(start, st.st_size);
+ close(fd1);
+ if (!atf_utils_compare_file("out.txt", "line\r\ntest@plop.meh\r\nline2\r\n\r\n")) {
+ atf_utils_cat_file("out.txt", ">");
+ atf_tc_fail("Unexpected output");
+ }
+
+
+ /* No to header */
+ f = fopen("myemailbody.txt", "w");
+ fprintf(f, "line\n\nline2\n\n");
+ fclose(f);
+ fd1 = open("myemailbody.txt", O_RDONLY);
+ fstat(fd1, &st);
+ ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
+ fd = open("out.txt", O_CREAT|O_TRUNC|O_WRONLY, 0644);
+ ATF_REQUIRE_EQ(write_mailbody_from_map(fd, start, st.st_size, NULL), 0);
+ close(fd);
+ munmap(start, st.st_size);
+ close(fd1);
+ if (!atf_utils_compare_file("out.txt", "line\r\n\r\nline2\r\n\r\n")) {
+ atf_utils_cat_file("out.txt", ">");
+ atf_tc_fail("Unexpected output");
+ }
+
+ /* With invalid socket */
+ f = fopen("myemailbody.txt", "w");
+ fprintf(f, "line\n");
+ fclose(f);
+ fd1 = open("myemailbody.txt", O_RDONLY);
+ fstat(fd1, &st);
+ ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
+ ATF_REQUIRE_EQ(write_mailbody_from_map(-1, start, st.st_size, "test@plop.meh"), -1);
+ munmap(start, st.st_size);
+ close(fd1);
+}
+
+
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, random_int);
ATF_TP_ADD_TC(tp, exec_and_wait);
ATF_TP_ADD_TC(tp, find_email_adr);
ATF_TP_ADD_TC(tp, strtoim);
+ ATF_TP_ADD_TC(tp, write_ehlo);
+ ATF_TP_ADD_TC(tp, write_helo);
+ ATF_TP_ADD_TC(tp, write_dot);
+ ATF_TP_ADD_TC(tp, write_data);
+ ATF_TP_ADD_TC(tp, write_quit);
+ ATF_TP_ADD_TC(tp, write_rset);
+ ATF_TP_ADD_TC(tp, write_replyto);
+ ATF_TP_ADD_TC(tp, write_rcpt_to);
+ ATF_TP_ADD_TC(tp, write_mail_from);
+ ATF_TP_ADD_TC(tp, write_mailbody_from_map);
return (atf_no_error());
}