commit 26014c6ffb0b3a3a446e837eaa931534b39e8e1b
parent b786fbad54ce8d965e324721e1736b40ab830009
Author: pancake@localhost.localdomain <unknown>
Date: Sun, 1 Nov 2009 20:58:22 +0100
* Initial non usable SSL support in sock.c (imap+pop3)
* Adapt 'dmc' start and -c commands to the new pipeline
* Adapt imap4 to the new pipeline format
- Make it work again
- Fix read lock
Diffstat:
Makefile | | | 10 | ++++++++-- |
README | | | 4 | +--- |
config.def.h | | | 2 | +- |
config.mk | | | 1 | + |
dmc | | | 47 | +++++++---------------------------------------- |
doc/send | | | 13 | +++++++++++++ |
imap4.c | | | 109 | +++++++++++++++++++++++++++++++------------------------------------------------ |
pop3.c | | | 19 | ++++++++++--------- |
sock.c | | | 39 | +++++++++++++++++++++++++++++++++++++-- |
9 files changed, 121 insertions(+), 123 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,20 +1,26 @@
include config.mk
+ifeq ($(HAVE_SSL),1)
+SSL_LIBS=`pkg-config libssl --libs`
+CFLAGS+=`pkg-config libssl --cflags`
+endif
+
all: config.h dmc-smtp dmc-pop3 dmc-imap4 dmc-pack
config.h:
@echo creating $@ from config.def.h
cp config.def.h config.h
+ ${MAKE} clean
dmc-smtp: smtp.o
${CC} ${LDFLAGS} smtp.o -o dmc-smtp -lresolv
# sock.c ?
dmc-pop3: pop3.o
- ${CC} ${LDFLAGS} pop3.o -o dmc-pop3
+ ${CC} ${LDFLAGS} ${SSL_LIBS} pop3.o -o dmc-pop3
dmc-imap4: imap4.o
- ${CC} ${LDFLAGS} imap4.o -o dmc-imap4
+ ${CC} ${LDFLAGS} ${SSL_LIBS} imap4.o -o dmc-imap4
dmc-pack: pack.o
${CC} ${LDFLAGS} pack.o -o dmc-pack
diff --git a/README b/README
@@ -5,9 +5,7 @@ dmc is a minimalist email client solution
Requirements
------------
- netcat (nc) for plain TCP connections
- openssl binary for SSL encrypted
- msmtp if you want to use
+ msmtp to send emails (dmc-smtp is not implemented yet)
Installation
diff --git a/config.def.h b/config.def.h
@@ -1 +1 @@
-#define HAVE_SSL 0
+#define HAVE_SSL 1
diff --git a/config.mk b/config.mk
@@ -2,5 +2,6 @@ VERSION = 0.1
PREFIX ?= /usr
CFLAGS ?= -Wall
+HAVE_SSL=1
CC ?= gcc
diff --git a/dmc b/dmc
@@ -15,57 +15,24 @@ mkdir -p ~/.dmc/acc
[ -e ~/.dmc/acc.default ] && . ~/.dmc/acc.default
function acc_daemon {
- FIFO=~/.dmc/tmp/${NAME}.fifo
- OUTF=~/.dmc/tmp/${NAME}.out
+ LOCK=~/.dmc/tmp/${NAME}.lock
INPUT=~/.dmc/tmp/${NAME}.input
OUTPUT=~/.dmc/tmp/${NAME}.output
- if [ "${SSL}" = 1 ]; then
- NETCMD="openssl s_client -quiet -host $HOST -port $POST"
- # TODO: Add decent support for certification check and reviewing
- # First connection must store the certificate in ~/.dmc/acc/ssl.cert
- # NETCMD="openssl s_client -cert '${CERT}' -verify 1 -quiet -host $HOST -port $POST"
- else
- NETCMD="nc $HOST $PORT"
- fi
-
echo "Starting $NAME account daemon..."
- rm -f "${INPUT}" "${FIFO}" "${OUTF}"
- mkfifo "${INPUT}" "${FIFO}"
-# XXX output must be also a fifo?!?
- :> ${OUTF}
+ rm -f "${LOCK}" "${INPUT}" "${OUTPUT}"
+ mkfifo "${LOCK}" "${INPUT}"
echo login ${USER} ${PASS} > ${INPUT} &
(while : ; do cat ${INPUT} 2> /dev/null ; done) | \
- dmc-${PROTOCOL} ${FIFO} ${OUTF} 2> ${OUTPUT} | $NETCMD > $FIFO
- rm -f ${INPUT}
+ dmc-${PROTOCOL} ${HOST} ${PORT} ${SSL} 2> ${OUTPUT} > ${LOCK}
+ rm -f "${LOCK}" "${INPUT}" "${OUTPUT}"
}
function dmc_cmd {
-# while not 0x00 is found...sleep 1
- #:> ~/.dmc/tmp/${NAME}.output
- # XXX this is going to fail and lock
- OUT=~/.dmc/tmp/${NAME}.output
- :> ${OUT}
echo "$@" > ~/.dmc/tmp/${NAME}.input
- # XXX ultraugly way to check for eof
- cat ~/.dmc/tmp/${NAME}.output # barrier
- cat ${OUT}
- osize=0
- while : ; do
- size=`du -hs ${OUT}|awk '{print $1}'`
- if [ "$size" = 0 ]; then
- sleep 1
- else
- if [ "$size" = "$osize" ]; then
- break
- else
- sleep 1
- osize=$size
- fi
- fi
- done
- cat ${OUT}
+ head -n 1 ~/.dmc/tmp/${NAME}.lock
+ cat ~/.dmc/tmp/${NAME}.output
}
function start_account_daemons {
diff --git a/doc/send b/doc/send
@@ -0,0 +1,13 @@
+dmc-send
+========
+
+send methods (in config.h?)
+ - mbox write
+ - maildir write
+ - |mail
+ - |msmtp
+ - MX + connect (auto smtp)
+ - nc localhost 25
+
+Must support more than one chained send methods
+ - to move a mail into the sent folder f.ex?
diff --git a/imap4.c b/imap4.c
@@ -9,13 +9,11 @@
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
-
+#include "sock.c"
static char *cmd = NULL;
static char word[4096];
static int ctr = 1;
-static char *fifo, *outf;
-static int ff, fo;
static char *dir;
/* TODO: make getword() ready() and cleanup() shared between smtp,pop,imap? */
@@ -55,35 +53,25 @@ reread:
return word;
}
-static void cleanup(int foo) {
- close(ff);
- unlink(fifo);
- exit(0);
-}
-
-static int ready() {
- struct pollfd fds[1];
- fds[0].fd = ff;
- fds[0].events = POLLIN|POLLPRI;
- fds[0].revents = POLLNVAL|POLLHUP|POLLERR;
- return poll((struct pollfd *)&fds, 1, 10);
+static void cleanup (void) {
+ sock_close ();
+ exit (0);
}
static int waitreply() {
char *ptr, *str = word;
int lock = 1;
int line = 0;
- int ret, reply = -1;
+ int reply = -1;
char result[256];
- ftruncate (fo, 0);
- while(lock || !ready()) {
+
+ ftruncate (2, 0);
+ *str = 0;
+ result[0] = '\0';
+ while(lock || sock_ready()) {
lock = 0;
- ret = read(ff, str, 1024);
- if (ret<1) {
- fprintf(stderr, " BREAK BREAK\n");
+ if (sock_read (str, 2024) <1)
break;
- }
- str[ret] = 0;
if (line == 0) {
ptr = strchr(word, ' ');
if (ptr) {
@@ -96,19 +84,14 @@ static int waitreply() {
if (!memcmp(ptr+1, "BAD", 3))
reply = 0;
}
- // XXX: Fix output, just show first line
- snprintf(result, 254, "### %s %d \"%s\"\n", cmd, reply, str);
+ snprintf (result, 254, "### %s %d \"%s\"\n", cmd, reply, str);
}
str = str+strlen(str);
line++;
- write (fo, str, strlen (str));
- // fprintf(stderr, "--> %s\n", str);
}
- //fprintf (stderr, "==> (((%s)))\n", word);
- write (fo, word, strlen (word));
- //fflush (stderr);
- write (2, result, strlen(result));
+ write (2, word, strlen (word));
+ write (1, result, strlen(result));
return reply;
}
@@ -121,7 +104,7 @@ CLOSE - commit the delete stuff (maybe must be done after rm)
EXPUNGE - permanent remove of deltec
RECENT - show the number of recent messages
#endif
-static int doword(char *word) {
+static int doword (char *word) {
int ret = 1;
free (cmd);
cmd = strdup(word);
@@ -129,12 +112,12 @@ static int doword(char *word) {
/* Do nothing */
} else
if (!strcmp(word, "exit")) {
- printf("%d LOGOUT\n", ctr++);
+ sock_printf("%d LOGOUT\n", ctr++);
waitreply();
ret = 0;
} else
if (!strcmp(word, "help") || !strcmp(word, "?")) {
- fprintf(stderr, "Use: login exit find ls cat head rm rmdir mkdir mvdir\n");
+ fprintf(stderr, "Use: login exit find cd pwd ls cat head rm rmdir mkdir mvdir\n");
} else
if (!strcmp(word, "pwd")) {
fprintf(stderr, "%s\n", dir);
@@ -144,38 +127,37 @@ static int doword(char *word) {
dir = strdup(getword());
if (!strcmp(dir, "\"\""))
*dir=0;
- printf("%d SELECT \"%s\"\n", ctr++, dir);
+ sock_printf ("%d SELECT \"%s\"\n", ctr++, dir);
waitreply();
} else
if (!strcmp(word, "find")) {
- printf("%d SEARCH TEXT \"%s\"\n", ctr++, getword());
+ sock_printf ("%d SEARCH TEXT \"%s\"\n", ctr++, getword());
waitreply();
} else
if (!strcmp(word, "ls")) {
- printf("%d LIST \"%s\" *\n", ctr++, dir);
+ sock_printf ("%d LIST \"%s\" *\n", ctr++, dir);
waitreply();
} else
if (!strcmp(word, "cat")) {
- printf("%d FETCH %d body[]\n",
+ sock_printf ("%d FETCH %d body[]\n",
ctr++, atoi(getword()));
waitreply();
} else
if (!strcmp(word, "head")) {
- printf("%d FETCH %d body[header]\n",
+ sock_printf ("%d FETCH %d body[header]\n",
ctr++, atoi(getword()));
waitreply();
} else
if (!strcmp(word, "mvdir")) {
- printf("%d RENAME %s %s\n",
+ sock_printf ("%d RENAME %s %s\n",
ctr++, getword(), getword());
} else
if (!strcmp(word, "mkdir")) {
- printf("%d CREATE \"%s\"\n",
- ctr++, getword());
+ sock_printf ("%d CREATE \"%s\"\n", ctr++, getword());
} else
if (!strcmp(word, "rm")) {
- printf("%d DELE %d\n", ctr++, atoi(getword()));
- waitreply();
+ sock_printf ("%d DELE %d\n", ctr++, atoi(getword()));
+ waitreply ();
} else
if (!strcmp(word, "rmdir")) {
printf("%d DELETE \"%s\"\n",
@@ -183,37 +165,32 @@ static int doword(char *word) {
waitreply();
} else
if (!strcmp(word, "login")) {
- char *user = strdup(getword());
- char *pass = strdup(getword());
- printf("%d LOGIN \"%s\" \"%s\"\n",
+ char *user = strdup (getword ());
+ char *pass = strdup (getword ());
+ sock_printf ("%d LOGIN \"%s\" \"%s\"\n",
ctr++, user, pass);
- free(user);
- free(pass);
+ free (user);
+ free (pass);
waitreply();
} else {
- printf("%d NOOP\n", ctr++);
+ sock_printf ("%d NOOP\n", ctr++);
waitreply();
}
return ret;
}
-int main(int argc, char **argv) {
- int ret = 0;
+int main (int argc, char **argv) {
+ int ssl = 0, ret = 0;
if (argc>2) {
- signal(SIGINT, cleanup);
- fifo = argv[1];
- outf = argv[2];
- mkfifo (fifo, 0600);
- unlink (outf);
- ff = open (fifo, O_RDONLY);
- fo = open (outf, O_WRONLY|O_CREAT, 0600);
- if (ff != -1 && fo != -1) {
- dir = strdup("");
- waitreply();
- while(doword(getword()));
- cleanup(0);
+ if (argc>3)
+ ssl = (*argv[3]=='1');
+ if (sock_connect (argv[1], atoi (argv[2]), ssl) >= 0) {
ret = 0;
- } else fprintf(stderr, "Cannot open fifo file.\n");
- } else fprintf(stderr, "Usage: dmc-imap4 fifo-in fifo-out | nc host 443 > fifo\n");
+ atexit (cleanup);
+ waitreply ();
+ dir = strdup ("");
+ while (doword (getword()));
+ } else fprintf (stderr, "Cannot connect to %s %d\n", argv[1], atoi(argv[2]));
+ } else fprintf(stderr, "Usage: dmc-imap4 host port 2> body > fifo < input\n");
return ret;
}
diff --git a/pop3.c b/pop3.c
@@ -22,7 +22,7 @@ static char *getword () {
}
static int waitreply() {
- char result[1024];
+ char result[256];
char *ch, *str = word;
int lock = 1;
int reply = -1;
@@ -47,16 +47,16 @@ static int waitreply() {
}
}
// TODO: \r \n issues
- ch = strstr(str, "\r\n.");
+ ch = strstr (str, "\r\n.");
if (ch)
*ch = '\0';
//fprintf(stderr, "%s\n", str);
fputs (str, stderr);
}
- fputs("", stderr);
- fflush(stderr);
+ fputs ("", stderr);
+ fflush (stderr);
fputs (result, stdout);
- fflush(stdout);
+ fflush (stdout);
/* stderr lseek works on pipes :D */
lseek (2, 0, 0);
return reply;
@@ -109,15 +109,16 @@ static void cleanup (void) {
}
int main(int argc, char **argv) {
- int ret = 1;
+ int ssl = 0, ret = 1;
if (argc>2) {
- if (sock_connect (argv[1], atoi (argv[2])) >= 0) {
+ if (argc>3)
+ ssl = (*argv[3]=='1');
+ if (sock_connect (argv[1], atoi (argv[2]), ssl) >= 0) {
ret = 0;
atexit (cleanup);
waitreply ();
while (doword (getword()));
- cleanup ();
} else fprintf (stderr, "Cannot connect to %s %d\n", argv[1], atoi(argv[2]));
- } else fprintf (stderr, "Usage: dmc-pop3 host port 2> body > fifo < input\n");
+ } else fprintf (stderr, "Usage: dmc-pop3 host port [ssl] 2> body > fifo < input\n");
return 0;
}
diff --git a/sock.c b/sock.c
@@ -13,15 +13,36 @@
#if HAVE_SSL
#include <openssl/ssl.h>
static int ssl = 0;
+static SSL_CTX *ctx;
+static SSL *sfd;
#endif
static int fd = -1;
+int sock_ssl (int enable) {
+#if HAVE_SSL
+ int err;
+ if (ssl) {
+ // challenge, check cert, etc..
+ sfd = SSL_new (ctx);
+ SSL_set_fd (sfd, fd);
+ err = SSL_connect (sfd);
+ /* TODO: check cert */
+ SSL_set_accept_state (sfd);
+ }
+ ssl = enable;
+ return 1;
+#else
+ return 0;
+#endif
+}
+
// TODO: cleanup all those fd=-1
-int sock_connect (const char *host, int port) {
+int sock_connect (const char *host, int port, int ssl) {
struct sockaddr_in sa;
struct hostent *he;
int s = socket (AF_INET, SOCK_STREAM, 0);
+ sock_ssl (ssl);
fd = -1;
if (s != -1) {
fd = s;
@@ -49,10 +70,18 @@ static int sock_ready() {
}
int sock_close () {
+#if HAVE_SSL
+ SSL_free (sfd);
+#endif
return close (fd);
}
int sock_write (const char *str) {
+#if HAVE_SSL
+ if (ssl)
+ return SSL_write (sfd, str, strlen(str));
+ else
+#endif
return write (fd, str, strlen(str));
}
@@ -69,7 +98,13 @@ int sock_printf (const char *fmt, ...) {
}
int sock_read (char *buf, int len) {
- int ret = read (fd, buf, 1024);
+ int ret;
+#if HAVE_SSL
+ if (ssl)
+ ret = SSL_read (sfd, buf, 1024);
+ else
+#endif
+ ret = read (fd, buf, 1024);
if (ret>0)
buf[ret] = '\0';
return ret;