aboutsummaryrefslogtreecommitdiffstats
path: root/smtpscript
diff options
context:
space:
mode:
authorGilles Chehade <gilles@poolp.org>2020-04-30 02:01:35 +0200
committerGilles Chehade <gilles@poolp.org>2020-04-30 02:01:35 +0200
commit6fb3965e81d9e4278ee5d96c2d68c014df1f3802 (patch)
treec3c895a4a39d4888e0ff978c97587120712a6b9d /smtpscript
parentplug ubuntu-gcc10 to CI (diff)
downloadOpenSMTPD-6fb3965e81d9e4278ee5d96c2d68c014df1f3802.tar.xz
OpenSMTPD-6fb3965e81d9e4278ee5d96c2d68c014df1f3802.zip
move
Diffstat (limited to 'smtpscript')
-rw-r--r--smtpscript/LICENSE15
-rw-r--r--smtpscript/Makefile3
-rw-r--r--smtpscript/Makefile.inc3
-rw-r--r--smtpscript/README.md40
-rw-r--r--smtpscript/iobuf.c466
-rw-r--r--smtpscript/iobuf.h71
-rw-r--r--smtpscript/parse.y905
-rw-r--r--smtpscript/smtpscript.c1009
-rw-r--r--smtpscript/smtpscript.h79
-rw-r--r--smtpscript/smtpscript/Makefile12
-rw-r--r--smtpscript/ssl.c167
11 files changed, 0 insertions, 2770 deletions
diff --git a/smtpscript/LICENSE b/smtpscript/LICENSE
deleted file mode 100644
index 92859014..00000000
--- a/smtpscript/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (c) 2013-2014 Eric Faurot <eric@openbsd.org>
- *
- * 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.
- */
diff --git a/smtpscript/Makefile b/smtpscript/Makefile
deleted file mode 100644
index 6a628f2a..00000000
--- a/smtpscript/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-SUBDIR+= smtpscript
-
-.include <bsd.subdir.mk>
diff --git a/smtpscript/Makefile.inc b/smtpscript/Makefile.inc
deleted file mode 100644
index be93057b..00000000
--- a/smtpscript/Makefile.inc
+++ /dev/null
@@ -1,3 +0,0 @@
-CFLAGS= -Wall -W
-
-BINDIR?= /usr/bin
diff --git a/smtpscript/README.md b/smtpscript/README.md
deleted file mode 100644
index 18f5fe9e..00000000
--- a/smtpscript/README.md
+++ /dev/null
@@ -1,40 +0,0 @@
-smtpscript
-==========
-
-smtpscript is a tool to write SMTP scenarios and easily implement regression tests for SMTP server-side implementations.
-
-A smtpscript will look like:
-
-
- # this is a function init-helo that we want to call in all our regress tests
- proc init-helo {
- expect smtp ok
- writeln "HELO regress"
- expect smtp helo
- }
-
- # each of the test-case will be called sequentially
- test-case name "mailfrom.empty" {
- call init-helo
- writeln "MAIL FROM:<>"
- expect smtp ok
- }
-
- test-case name "mailfrom.broken" {
- call init-helo
- writeln "MAIL FROM:< @bleh>"
- expect smtp permfail
- }
-
-
-which once executed, produces the output:
-
- $ smtpscript foo
- ===> running test-case "mailfrom.empty" ok
- ===> running test-case "mailfrom.broken" ok
- ===> all run
- passed: 2/2 (skipped: 0, failed: 0, error: 0)
- $
-
-
-The scripting language also supports TLS, randomization and loops, so fairly complex scenarios can be achieved.
diff --git a/smtpscript/iobuf.c b/smtpscript/iobuf.c
deleted file mode 100644
index 05a9cd59..00000000
--- a/smtpscript/iobuf.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/* $OpenBSD$ */
-/*
- * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
- *
- * 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.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#ifdef IO_TLS
-#include <openssl/err.h>
-#include <openssl/ssl.h>
-#endif
-
-#include "iobuf.h"
-
-#define IOBUF_MAX 65536
-#define IOBUFQ_MIN 4096
-
-struct ioqbuf *ioqbuf_alloc(struct iobuf *, size_t);
-void iobuf_drain(struct iobuf *, size_t);
-
-int
-iobuf_init(struct iobuf *io, size_t size, size_t max)
-{
- memset(io, 0, sizeof *io);
-
- if (max == 0)
- max = IOBUF_MAX;
-
- if (size == 0)
- size = max;
-
- if (size > max)
- return (-1);
-
- if ((io->buf = malloc(size)) == NULL)
- return (-1);
-
- io->size = size;
- io->max = max;
-
- return (0);
-}
-
-void
-iobuf_clear(struct iobuf *io)
-{
- struct ioqbuf *q;
-
- if (io->buf)
- free(io->buf);
-
- while ((q = io->outq)) {
- io->outq = q->next;
- free(q);
- }
-
- memset(io, 0, sizeof (*io));
-}
-
-void
-iobuf_drain(struct iobuf *io, size_t n)
-{
- struct ioqbuf *q;
- size_t left = n;
-
- while ((q = io->outq) && left) {
- if ((q->wpos - q->rpos) > left) {
- q->rpos += left;
- left = 0;
- } else {
- left -= q->wpos - q->rpos;
- io->outq = q->next;
- free(q);
- }
- }
-
- io->queued -= (n - left);
- if (io->outq == NULL)
- io->outqlast = NULL;
-}
-
-int
-iobuf_extend(struct iobuf *io, size_t n)
-{
- char *t;
-
- if (n > io->max)
- return (-1);
-
- if (io->max - io->size < n)
- return (-1);
-
- t = realloc(io->buf, io->size + n);
- if (t == NULL)
- return (-1);
-
- io->size += n;
- io->buf = t;
-
- return (0);
-}
-
-size_t
-iobuf_left(struct iobuf *io)
-{
- return io->size - io->wpos;
-}
-
-size_t
-iobuf_space(struct iobuf *io)
-{
- return io->size - (io->wpos - io->rpos);
-}
-
-size_t
-iobuf_len(struct iobuf *io)
-{
- return io->wpos - io->rpos;
-}
-
-char *
-iobuf_data(struct iobuf *io)
-{
- return io->buf + io->rpos;
-}
-
-void
-iobuf_drop(struct iobuf *io, size_t n)
-{
- if (n >= iobuf_len(io)) {
- io->rpos = io->wpos = 0;
- return;
- }
-
- io->rpos += n;
-}
-
-char *
-iobuf_getline(struct iobuf *iobuf, size_t *rlen)
-{
- char *buf;
- size_t len, i;
-
- buf = iobuf_data(iobuf);
- len = iobuf_len(iobuf);
-
- for (i = 0; i + 1 <= len; i++)
- if (buf[i] == '\n') {
- /* Note: the returned address points into the iobuf
- * buffer. We NUL-end it for convenience, and discard
- * the data from the iobuf, so that the caller doesn't
- * have to do it. The data remains "valid" as long
- * as the iobuf does not overwrite it, that is until
- * the next call to iobuf_normalize() or iobuf_extend().
- */
- iobuf_drop(iobuf, i + 1);
- len = (i && buf[i - 1] == '\r') ? i - 1 : i;
- buf[len] = '\0';
- if (rlen)
- *rlen = len;
- return (buf);
- }
-
- return (NULL);
-}
-
-void
-iobuf_normalize(struct iobuf *io)
-{
- if (io->rpos == 0)
- return;
-
- if (io->rpos == io->wpos) {
- io->rpos = io->wpos = 0;
- return;
- }
-
- memmove(io->buf, io->buf + io->rpos, io->wpos - io->rpos);
- io->wpos -= io->rpos;
- io->rpos = 0;
-}
-
-ssize_t
-iobuf_read(struct iobuf *io, int fd)
-{
- ssize_t n;
-
- n = read(fd, io->buf + io->wpos, iobuf_left(io));
- if (n == -1) {
- /* XXX is this really what we want? */
- if (errno == EAGAIN || errno == EINTR)
- return (IOBUF_WANT_READ);
- return (IOBUF_ERROR);
- }
- if (n == 0)
- return (IOBUF_CLOSED);
-
- io->wpos += n;
-
- return (n);
-}
-
-struct ioqbuf *
-ioqbuf_alloc(struct iobuf *io, size_t len)
-{
- struct ioqbuf *q;
-
- if (len < IOBUFQ_MIN)
- len = IOBUFQ_MIN;
-
- if ((q = malloc(sizeof(*q) + len)) == NULL)
- return (NULL);
-
- q->rpos = 0;
- q->wpos = 0;
- q->size = len;
- q->next = NULL;
- q->buf = (char *)(q) + sizeof(*q);
-
- if (io->outqlast == NULL)
- io->outq = q;
- else
- io->outqlast->next = q;
- io->outqlast = q;
-
- return (q);
-}
-
-size_t
-iobuf_queued(struct iobuf *io)
-{
- return io->queued;
-}
-
-void *
-iobuf_reserve(struct iobuf *io, size_t len)
-{
- struct ioqbuf *q;
- void *r;
-
- if (len == 0)
- return (NULL);
-
- if (((q = io->outqlast) == NULL) || q->size - q->wpos <= len) {
- if ((q = ioqbuf_alloc(io, len)) == NULL)
- return (NULL);
- }
-
- r = q->buf + q->wpos;
- q->wpos += len;
- io->queued += len;
-
- return (r);
-}
-
-int
-iobuf_queue(struct iobuf *io, const void *data, size_t len)
-{
- void *buf;
-
- if (len == 0)
- return (0);
-
- if ((buf = iobuf_reserve(io, len)) == NULL)
- return (-1);
-
- memmove(buf, data, len);
-
- return (0);
-}
-
-int
-iobuf_queuev(struct iobuf *io, const struct iovec *iov, int iovcnt)
-{
- int i;
- size_t len = 0;
- char *buf;
-
- for (i = 0; i < iovcnt; i++)
- len += iov[i].iov_len;
-
- if ((buf = iobuf_reserve(io, len)) == NULL)
- return (-1);
-
- for (i = 0; i < iovcnt; i++) {
- if (iov[i].iov_len == 0)
- continue;
- memmove(buf, iov[i].iov_base, iov[i].iov_len);
- buf += iov[i].iov_len;
- }
-
- return (0);
-
-}
-
-int
-iobuf_fqueue(struct iobuf *io, const char *fmt, ...)
-{
- va_list ap;
- int len;
-
- va_start(ap, fmt);
- len = iobuf_vfqueue(io, fmt, ap);
- va_end(ap);
-
- return (len);
-}
-
-int
-iobuf_vfqueue(struct iobuf *io, const char *fmt, va_list ap)
-{
- char *buf;
- int len;
-
- len = vasprintf(&buf, fmt, ap);
-
- if (len == -1)
- return (-1);
-
- len = iobuf_queue(io, buf, len);
- free(buf);
-
- return (len);
-}
-
-ssize_t
-iobuf_write(struct iobuf *io, int fd)
-{
- struct iovec iov[IOV_MAX];
- struct ioqbuf *q;
- int i;
- ssize_t n;
-
- i = 0;
- for (q = io->outq; q ; q = q->next) {
- if (i >= IOV_MAX)
- break;
- iov[i].iov_base = q->buf + q->rpos;
- iov[i].iov_len = q->wpos - q->rpos;
- i++;
- }
-
- n = writev(fd, iov, i);
- if (n == -1) {
- if (errno == EAGAIN || errno == EINTR)
- return (IOBUF_WANT_WRITE);
- if (errno == EPIPE)
- return (IOBUF_CLOSED);
- return (IOBUF_ERROR);
- }
-
- iobuf_drain(io, n);
-
- return (n);
-}
-
-int
-iobuf_flush(struct iobuf *io, int fd)
-{
- ssize_t s;
-
- while (io->queued)
- if ((s = iobuf_write(io, fd)) < 0)
- return (s);
-
- return (0);
-}
-
-#ifdef IO_TLS
-
-int
-iobuf_flush_ssl(struct iobuf *io, void *ssl)
-{
- ssize_t s;
-
- while (io->queued)
- if ((s = iobuf_write_ssl(io, ssl) < 0))
- return (s);
-
- return (0);
-}
-
-ssize_t
-iobuf_write_ssl(struct iobuf *io, void *ssl)
-{
- struct ioqbuf *q;
- int r;
- ssize_t n;
-
- q = io->outq;
- n = SSL_write(ssl, q->buf + q->rpos, q->wpos - q->rpos);
- if (n <= 0) {
- switch ((r = SSL_get_error(ssl, n))) {
- case SSL_ERROR_WANT_READ:
- return (IOBUF_WANT_READ);
- case SSL_ERROR_WANT_WRITE:
- return (IOBUF_WANT_WRITE);
- case SSL_ERROR_ZERO_RETURN: /* connection closed */
- return (IOBUF_CLOSED);
- case SSL_ERROR_SYSCALL:
- if (ERR_peek_last_error())
- return (IOBUF_SSLERROR);
- if (r == 0)
- errno = EPIPE;
- return (IOBUF_ERROR);
- default:
- return (IOBUF_SSLERROR);
- }
- }
- iobuf_drain(io, n);
-
- return (n);
-}
-
-ssize_t
-iobuf_read_ssl(struct iobuf *io, void *ssl)
-{
- ssize_t n;
- int r;
-
- n = SSL_read(ssl, io->buf + io->wpos, iobuf_left(io));
- if (n < 0) {
- switch ((r = SSL_get_error(ssl, n))) {
- case SSL_ERROR_WANT_READ:
- return (IOBUF_WANT_READ);
- case SSL_ERROR_WANT_WRITE:
- return (IOBUF_WANT_WRITE);
- case SSL_ERROR_SYSCALL:
- if (ERR_peek_last_error())
- return (IOBUF_SSLERROR);
- if (r == 0)
- errno = EPIPE;
- return (IOBUF_ERROR);
- default:
- return (IOBUF_SSLERROR);
- }
- } else if (n == 0)
- return (IOBUF_CLOSED);
-
- io->wpos += n;
-
- return (n);
-}
-
-#endif /* IO_TLS */
diff --git a/smtpscript/iobuf.h b/smtpscript/iobuf.h
deleted file mode 100644
index ee4690c8..00000000
--- a/smtpscript/iobuf.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* $OpenBSD$ */
-/*
- * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
- *
- * 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.
- */
-
-#include <sys/types.h>
-
-#include <stdarg.h>
-
-struct ioqbuf {
- struct ioqbuf *next;
- char *buf;
- size_t size;
- size_t wpos;
- size_t rpos;
-};
-
-struct iobuf {
- char *buf;
- size_t max;
- size_t size;
- size_t wpos;
- size_t rpos;
-
- size_t queued;
- struct ioqbuf *outq;
- struct ioqbuf *outqlast;
-};
-
-#define IOBUF_WANT_READ -1
-#define IOBUF_WANT_WRITE -2
-#define IOBUF_CLOSED -3
-#define IOBUF_ERROR -4
-#define IOBUF_SSLERROR -5
-
-int iobuf_init(struct iobuf *, size_t, size_t);
-void iobuf_clear(struct iobuf *);
-
-int iobuf_extend(struct iobuf *, size_t);
-void iobuf_normalize(struct iobuf *);
-void iobuf_drop(struct iobuf *, size_t);
-size_t iobuf_space(struct iobuf *);
-size_t iobuf_len(struct iobuf *);
-size_t iobuf_left(struct iobuf *);
-char *iobuf_data(struct iobuf *);
-char *iobuf_getline(struct iobuf *, size_t *);
-ssize_t iobuf_read(struct iobuf *, int);
-ssize_t iobuf_read_ssl(struct iobuf *, void *);
-
-size_t iobuf_queued(struct iobuf *);
-void* iobuf_reserve(struct iobuf *, size_t);
-int iobuf_queue(struct iobuf *, const void*, size_t);
-int iobuf_queuev(struct iobuf *, const struct iovec *, int);
-int iobuf_fqueue(struct iobuf *, const char *, ...);
-int iobuf_vfqueue(struct iobuf *, const char *, va_list);
-int iobuf_flush(struct iobuf *, int);
-int iobuf_flush_ssl(struct iobuf *, void *);
-ssize_t iobuf_write(struct iobuf *, int);
-ssize_t iobuf_write_ssl(struct iobuf *, void *);
diff --git a/smtpscript/parse.y b/smtpscript/parse.y
deleted file mode 100644
index 47a0f35c..00000000
--- a/smtpscript/parse.y
+++ /dev/null
@@ -1,905 +0,0 @@
-/* $OpenBSD: parse.y,v 1.109 2012/10/14 11:58:23 gilles Exp $ */
-
-/*
- * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
- * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
- * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
- * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
- * Copyright (c) 2001 Theo de Raadt. All rights reserved.
- *
- * 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.
- */
-
-%{
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/tree.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <event.h>
-#include <inttypes.h>
-#include <netdb.h>
-#include <paths.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <util.h>
-
-#include "smtpscript.h"
-
-TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
-static struct file {
- TAILQ_ENTRY(file) entry;
- FILE *stream;
- char *name;
- int lineno;
- int errors;
-} *file, *topfile;
-struct file *pushfile(const char *, int);
-int popfile(void);
-int check_file_secrecy(int, const char *);
-int yyparse(void);
-int yylex(void);
-int kw_cmp(const void *, const void *);
-int lookup(char *);
-int lgetc(int);
-int lungetc(int);
-int findeol(void);
-int yyerror(const char *, ...)
- __attribute__ ((format (printf, 1, 2)));
-
-TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
-struct sym {
- TAILQ_ENTRY(sym) entry;
- int used;
- int persist;
- char *nam;
- char *val;
-};
-int symset(const char *, const char *, int);
-char *symget(const char *);
-
-void push_op(struct op *);
-struct op *peek_op(void);
-struct op *pop_op(void);
-
-#define MAXDEPTH 50
-
-static struct op * opstack[MAXDEPTH];
-static int opstackidx;
-
-static int errors = 0;
-
-static struct script *currscript;
-static struct procedure *currproc;
-
-int delaytonum(char *);
-
-typedef struct {
- union {
- int64_t number;
- char *string;
- struct op *op;
- } v;
- int lineno;
-} YYSTYPE;
-
-%}
-
-%token INCLUDE PORT REPEAT RANDOM NOOP
-%token PROC TESTCASE NAME NO_AUTOCONNECT EXPECT FAIL SKIP
-%token CALL CONNECT DISCONNECT STARTTLS SLEEP WRITE WRITELN
-%token SMTP OK TEMPFAIL PERMFAIL HELO
-%token ERROR ARROW
-%token <v.string> STRING
-%token <v.number> NUMBER
-%type <v.number> quantifier port duration
-%type <v.op> statement block
-%%
-
-grammar : /* empty */
- | grammar '\n'
- | grammar include '\n'
- | grammar varset '\n'
- | grammar proc '\n'
- | grammar testcase '\n'
- | grammar error '\n' { file->errors++; }
- ;
-
-include : INCLUDE STRING {
- struct file *nfile;
-
- if ((nfile = pushfile($2, 0)) == NULL) {
- yyerror("failed to include file %s", $2);
- free($2);
- YYERROR;
- }
- free($2);
-
- file = nfile;
- lungetc('\n');
- }
- ;
-
-varset : STRING '=' STRING {
- if (symset($1, $3, 0) == -1)
- errx(1, "cannot store variable");
- free($1);
- free($3);
- }
- ;
-
-optnl : '\n' optnl
- |
- ;
-
-nl : '\n' optnl
- ;
-
-quantifier : /* empty */ { $$ = 1; }
- | 's' { $$ = 1000; }
- | 'm' { $$ = 60 * 1000; }
- | 'h' { $$ = 3600 * 1000; }
- ;
-
-duration : NUMBER quantifier {
- if ($1 < 0) {
- yyerror("invalid duration: %" PRId64, $1);
- YYERROR;
- }
- $$ = $1 * $2;
- }
- ;
-
-port : PORT STRING {
- struct servent *servent;
-
- servent = getservbyname($2, "tcp");
- if (servent == NULL) {
- yyerror("port %s is invalid", $2);
- free($2);
- YYERROR;
- }
- $$ = ntohs(servent->s_port);
- free($2);
- }
- | PORT NUMBER {
- if ($2 <= 0 || $2 >= (int)USHRT_MAX) {
- yyerror("invalid port: %" PRId64, $2);
- YYERROR;
- }
- $$ = $2;
- }
- | /* empty */ {
- $$ = 25;
- }
- ;
-
-statement : block
- | REPEAT NUMBER { push_op(NULL); } statement {
- pop_op();
- $$ = op_repeat(peek_op(), $2, $4);
- }
- | RANDOM { push_op(NULL); } block {
- pop_op();
- $$ = op_random(peek_op(), $3);
- }
- | CALL STRING {
- struct procedure *p;
- p = procedure_get_by_name(currscript, $2);
- if (p == NULL) {
- yyerror("call to undefined proc \"%s\"", $2);
- file->errors++;
- } else if (p == currproc) {
- yyerror("recursive call to proc \"%s\"", $2);
- file->errors++;
- } else {
- $$ = op_call(peek_op(), p);
- }
- free($2);
- }
- | NOOP {
- $$ = op_noop(peek_op());
- }
- | SLEEP duration {
- $$ = op_sleep(peek_op(), $2);
- }
- | FAIL STRING {
- $$ = op_fail(peek_op(), $2);
- }
- | CONNECT STRING port {
- $$ = op_connect(peek_op(), $2, $3);
- }
- | DISCONNECT {
- $$ = op_disconnect(peek_op());
- }
- | STARTTLS {
- $$ = op_starttls(peek_op());
- }
- | WRITE STRING {
- $$ = op_write(peek_op(), $2, strlen($2));
- }
- | WRITELN STRING {
- $$ = op_printf(peek_op(), "%s\r\n", $2);
- free($2);
- }
- | EXPECT DISCONNECT {
- $$ = op_expect_disconnect(peek_op());
- }
- | EXPECT SMTP {
- $$ = op_expect_smtp_response(peek_op(),
- RESP_SMTP_ANY | RESP_SMTP_MULTILINE);
- }
- | EXPECT SMTP OK {
- $$ = op_expect_smtp_response(peek_op(),
- RESP_SMTP_OK);
- }
- | EXPECT SMTP HELO {
- $$ = op_expect_smtp_response(peek_op(),
- RESP_SMTP_OK | RESP_SMTP_MULTILINE);
- }
- | EXPECT SMTP TEMPFAIL {
- $$ = op_expect_smtp_response(peek_op(),
- RESP_SMTP_TEMPFAIL);
- }
- | EXPECT SMTP PERMFAIL {
- $$ = op_expect_smtp_response(peek_op(),
- RESP_SMTP_PERMFAIL);
- }
- ;
-
-statement_list : statement nl statement_list
- | statement
- | /* EMPTY */
- ;
-
-block : '{' {
- push_op(op_block(peek_op()));
- } optnl statement_list '}' {
- $$ = pop_op();
- }
- ;
-
-procparam : '%' STRING {
- if (proc_addvar(currproc, $2) == -1) {
- yyerror("cannot add parameter %s", $2);
- file->errors++;
- }
- }
- ;
-
-procparams : procparam procparams
- | /* EMPTY */
- ;
-
-proc : PROC STRING {
- printf("# proc %s\n", $2);
- currproc = procedure_create(currscript, $2);
- if (currproc == NULL)
- file->errors++;
- } procparams block {
- if (currproc)
- currproc->root = $5;
- }
- ;
-
-testopt_name : NAME STRING {
- if (procedure_get_by_name(currscript, $2)) {
- file->errors++;
- } else {
- free(currproc->name);
- currproc->name = ($2);
- }
- }
- | /* EMPTY */
- ;
-
-testopt_cnx : NO_AUTOCONNECT {
- currproc->flags |= PROC_NOCONNECT;
- }
- | /* EMPTY */
- ;
-testopt_fail : EXPECT FAIL {
- currproc->flags |= PROC_EXPECTFAIL;
- }
- | /* EMPTY */
- ;
-
-testopt_skip : SKIP {
- currproc->flags |= PROC_SKIP;
- }
- | /* EMPTY */
- ;
-
-testcaseopts : testopt_name testopt_cnx testopt_fail testopt_skip;
-
-testcase : TESTCASE {
- char buf[1024];
- snprintf(buf, sizeof buf, "<%s:%i>",
- file->name, file->lineno);
- currproc = procedure_create(currscript, strdup(buf));
- if (currproc) {
- currproc->flags |= PROC_TESTCASE;
- } else {
- file->errors++;
- }
- } testcaseopts block {
- currproc->root = $4;
- }
- ;
-%%
-
-struct keywords {
- const char *k_name;
- int k_val;
-};
-
-int
-yyerror(const char *fmt, ...)
-{
- va_list ap;
-
- file->errors++;
- va_start(ap, fmt);
- fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
- return (0);
-}
-
-int
-kw_cmp(const void *k, const void *e)
-{
- return (strcmp(k, ((const struct keywords *)e)->k_name));
-}
-
-int
-lookup(char *s)
-{
- /* this has to be sorted always */
- static const struct keywords keywords[] = {
- { "call", CALL },
- { "connect", CONNECT },
- { "disconnect", DISCONNECT },
- { "expect", EXPECT },
- { "fail", FAIL },
- { "helo", HELO },
- { "name", NAME },
- { "no-autoconnect", NO_AUTOCONNECT },
- { "noop", NOOP },
- { "ok", OK },
- { "permfail", PERMFAIL },
- { "port", PORT },
- { "proc", PROC },
- { "random", RANDOM },
- { "repeat", REPEAT },
- { "skip", SKIP },
- { "sleep", SLEEP },
- { "smtp", SMTP },
- { "starttls", STARTTLS },
- { "tempfail", TEMPFAIL },
- { "test-case", TESTCASE },
- { "write", WRITE },
- { "writeln", WRITELN },
- };
- const struct keywords *p;
-
- p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
- sizeof(keywords[0]), kw_cmp);
-
- if (p)
- return (p->k_val);
- else
- return (STRING);
-}
-
-#define MAXPUSHBACK 128
-
-char *parsebuf;
-int parseindex;
-char pushback_buffer[MAXPUSHBACK];
-int pushback_index = 0;
-
-int
-lgetc(int quotec)
-{
- int c, next;
-
- if (parsebuf) {
- /* Read character from the parsebuffer instead of input. */
- if (parseindex >= 0) {
- c = parsebuf[parseindex++];
- if (c != '\0')
- return (c);
- parsebuf = NULL;
- } else
- parseindex++;
- }
-
- if (pushback_index)
- return (pushback_buffer[--pushback_index]);
-
- if (quotec) {
- if ((c = getc(file->stream)) == EOF) {
- yyerror("reached end of file while parsing "
- "quoted string");
- if (file == topfile || popfile() == EOF)
- return (EOF);
- return (quotec);
- }
- return (c);
- }
-
- while ((c = getc(file->stream)) == '\\') {
- next = getc(file->stream);
- if (next != '\n') {
- c = next;
- break;
- }
- yylval.lineno = file->lineno;
- file->lineno++;
- }
-
- while (c == EOF) {
- if (file == topfile || popfile() == EOF)
- return (EOF);
- c = getc(file->stream);
- }
- return (c);
-}
-
-int
-lungetc(int c)
-{
- if (c == EOF)
- return (EOF);
- if (parsebuf) {
- parseindex--;
- if (parseindex >= 0)
- return (c);
- }
- if (pushback_index < MAXPUSHBACK-1)
- return (pushback_buffer[pushback_index++] = c);
- else
- return (EOF);
-}
-
-int
-findeol(void)
-{
- int c;
-
- parsebuf = NULL;
- pushback_index = 0;
-
- /* skip to either EOF or the first real EOL */
- while (1) {
- c = lgetc(0);
- if (c == '\n') {
- file->lineno++;
- break;
- }
- if (c == EOF)
- break;
- }
- return (ERROR);
-}
-
-int
-yylex(void)
-{
- char buf[8096];
- char *p, *val;
- int quotec, next, c;
- int token;
-
-top:
- p = buf;
- while ((c = lgetc(0)) == ' ' || c == '\t')
- ; /* nothing */
-
- yylval.lineno = file->lineno;
- if (c == '#')
- while ((c = lgetc(0)) != '\n' && c != EOF)
- ; /* nothing */
- if (c == '$' && parsebuf == NULL) {
- while (1) {
- if ((c = lgetc(0)) == EOF)
- return (0);
-
- if (p + 1 >= buf + sizeof(buf) - 1) {
- yyerror("string too long");
- return (findeol());
- }
- if (isalnum(c) || c == '_') {
- *p++ = (char)c;
- continue;
- }
- *p = '\0';
- lungetc(c);
- break;
- }
- val = symget(buf);
- if (val == NULL) {
- yyerror("macro '%s' not defined", buf);
- return (findeol());
- }
- parsebuf = val;
- parseindex = 0;
- goto top;
- }
-
- switch (c) {
- case '\'':
- case '"':
- quotec = c;
- while (1) {
- if ((c = lgetc(quotec)) == EOF)
- return (0);
- if (c == '\n') {
- file->lineno++;
- continue;
- } else if (c == '\\') {
- if ((next = lgetc(quotec)) == EOF)
- return (0);
- if (next == quotec || c == ' ' || c == '\t')
- c = next;
- else if (next == '\n') {
- file->lineno++;
- continue;
- } else
- lungetc(next);
- } else if (c == quotec) {
- *p = '\0';
- break;
- }
- if (p + 1 >= buf + sizeof(buf) - 1) {
- yyerror("string too long");
- return (findeol());
- }
- *p++ = (char)c;
- }
- yylval.v.string = strdup(buf);
- if (yylval.v.string == NULL)
- err(1, "yylex: strdup");
- return (STRING);
- }
-
-#define allowed_to_end_number(x) \
- (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
-
- if (c == '-' || isdigit(c)) {
- do {
- *p++ = c;
- if ((unsigned)(p-buf) >= sizeof(buf)) {
- yyerror("string too long");
- return (findeol());
- }
- } while ((c = lgetc(0)) != EOF && isdigit(c));
- lungetc(c);
- if (p == buf + 1 && buf[0] == '-')
- goto nodigits;
- if (c == EOF || allowed_to_end_number(c)) {
- const char *errstr = NULL;
-
- *p = '\0';
- yylval.v.number = strtonum(buf, LLONG_MIN,
- LLONG_MAX, &errstr);
- if (errstr) {
- yyerror("\"%s\" invalid number: %s",
- buf, errstr);
- return (findeol());
- }
- return (NUMBER);
- } else {
-nodigits:
- while (p > buf + 1)
- lungetc(*--p);
- c = *--p;
- if (c == '-')
- return (c);
- }
- }
-
- if (c == '=') {
- if ((c = lgetc(0)) != EOF && c == '>')
- return (ARROW);
- lungetc(c);
- c = '=';
- }
-
-#define allowed_in_string(x) \
- (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
- x != '{' && x != '}' && x != '<' && x != '>' && \
- x != '!' && x != '=' && x != '#' && \
- x != ','))
-
- if (isalnum(c) || c == ':' || c == '_') {
- do {
- *p++ = c;
- if ((unsigned)(p-buf) >= sizeof(buf)) {
- yyerror("string too long");
- return (findeol());
- }
- } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
- lungetc(c);
- *p = '\0';
- if ((token = lookup(buf)) == STRING)
- if ((yylval.v.string = strdup(buf)) == NULL)
- err(1, "yylex: strdup");
- return (token);
- }
- if (c == '\n') {
- yylval.lineno = file->lineno;
- file->lineno++;
- }
- if (c == EOF)
- return (0);
- return (c);
-}
-
-int
-check_file_secrecy(int fd, const char *fname)
-{
- struct stat st;
-
- if (fstat(fd, &st)) {
- warn("cannot stat %s", fname);
- return (-1);
- }
- if (st.st_uid != 0 && st.st_uid != getuid()) {
- warnx("%s: owner not root or current user", fname);
- return (-1);
- }
- if (st.st_mode & (S_IRWXG | S_IRWXO)) {
- warnx("%s: group/world readable/writeable", fname);
- return (-1);
- }
- return (0);
-}
-
-struct file *
-pushfile(const char *name, int secret)
-{
- struct file *nfile;
-
- if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
- warn("malloc");
- return (NULL);
- }
- if ((nfile->name = strdup(name)) == NULL) {
- warn("malloc");
- free(nfile);
- return (NULL);
- }
- if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
- warn("%s", nfile->name);
- free(nfile->name);
- free(nfile);
- return (NULL);
- } else if (secret &&
- check_file_secrecy(fileno(nfile->stream), nfile->name)) {
- fclose(nfile->stream);
- free(nfile->name);
- free(nfile);
- return (NULL);
- }
- nfile->lineno = 1;
- TAILQ_INSERT_TAIL(&files, nfile, entry);
- return (nfile);
-}
-
-int
-popfile(void)
-{
- struct file *prev;
-
- if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
- prev->errors += file->errors;
-
- TAILQ_REMOVE(&files, file, entry);
- fclose(file->stream);
- free(file->name);
- free(file);
- file = prev;
- return (file ? 0 : EOF);
-}
-
-struct script *
-parse_script(const char *filename)
-{
- errors = 0;
-
- currscript = calloc(1, sizeof *currscript);
- TAILQ_INIT(&currscript->procs);
- currproc = NULL;
-
- opstackidx = 0;
-
- if ((file = pushfile(filename, 0)) == NULL)
- return (NULL);
-
- topfile = file;
-
- /*
- * parse configuration
- */
- setservent(1);
- yyparse();
- errors = file->errors;
- popfile();
- endservent();
-
- if (errors)
- return (NULL);
-
- return (currscript);
-}
-
-int
-symset(const char *nam, const char *val, int persist)
-{
- struct sym *sym;
-
- for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
- sym = TAILQ_NEXT(sym, entry))
- ; /* nothing */
-
- if (sym != NULL) {
- if (sym->persist == 1)
- return (0);
- else {
- free(sym->nam);
- free(sym->val);
- TAILQ_REMOVE(&symhead, sym, entry);
- free(sym);
- }
- }
- if ((sym = calloc(1, sizeof(*sym))) == NULL)
- return (-1);
-
- sym->nam = strdup(nam);
- if (sym->nam == NULL) {
- free(sym);
- return (-1);
- }
- sym->val = strdup(val);
- if (sym->val == NULL) {
- free(sym->nam);
- free(sym);
- return (-1);
- }
- sym->used = 0;
- sym->persist = persist;
- TAILQ_INSERT_TAIL(&symhead, sym, entry);
- return (0);
-}
-
-int
-cmdline_symset(char *s)
-{
- char *sym, *val;
- int ret;
- size_t len;
-
- if ((val = strrchr(s, '=')) == NULL)
- return (-1);
-
- len = strlen(s) - strlen(val) + 1;
- if ((sym = malloc(len)) == NULL)
- errx(1, "cmdline_symset: malloc");
-
- (void)strlcpy(sym, s, len);
-
- ret = symset(sym, val + 1, 1);
- free(sym);
-
- return (ret);
-}
-
-char *
-symget(const char *nam)
-{
- struct sym *sym;
-
- TAILQ_FOREACH(sym, &symhead, entry)
- if (strcmp(nam, sym->nam) == 0) {
- sym->used = 1;
- return (sym->val);
- }
- return (NULL);
-}
-
-int
-delaytonum(char *str)
-{
- unsigned int factor;
- size_t len;
- const char *errstr = NULL;
- int delay;
-
- /* we need at least 1 digit and 1 unit */
- len = strlen(str);
- if (len < 2)
- goto bad;
-
- switch(str[len - 1]) {
-
- case 's':
- factor = 1;
- break;
-
- case 'm':
- factor = 60;
- break;
-
- case 'h':
- factor = 60 * 60;
- break;
-
- case 'd':
- factor = 24 * 60 * 60;
- break;
-
- default:
- goto bad;
- }
-
- str[len - 1] = '\0';
- delay = strtonum(str, 1, INT_MAX / factor, &errstr);
- if (errstr)
- goto bad;
-
- return (delay * factor);
-
-bad:
- return (-1);
-}
-
-
-void
-push_op(struct op *op)
-{
- if (opstackidx == MAXDEPTH) {
- yyerror("too deep");
- return;
- }
- opstack[opstackidx++] = op;
-}
-
-struct op *
-pop_op(void)
-{
- if (opstackidx == 0)
- return (NULL);
- return (opstack[--opstackidx]);
-}
-
-struct op *
-peek_op(void)
-{
- if (opstackidx == 0)
- return (NULL);
- return (opstack[opstackidx - 1]);
-}
diff --git a/smtpscript/smtpscript.c b/smtpscript/smtpscript.c
deleted file mode 100644
index a75c4249..00000000
--- a/smtpscript/smtpscript.c
+++ /dev/null
@@ -1,1009 +0,0 @@
-/* $OpenBSD: iobuf.h,v 1.1 2012/01/29 00:32:51 eric Exp $ */
-/*
- * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
- *
- * 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.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/queue.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <getopt.h>
-#include <netdb.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <vis.h>
-
-#include "iobuf.h"
-
-#include "smtpscript.h"
-
-void *ssl_connect(int);
-void ssl_close(void *);
-
-/* XXX */
-#define SMTP_LINE_MAX 4096
-
-enum {
- OP_BLOCK,
- OP_REPEAT,
- OP_RANDOM,
-
- OP_NOOP,
-
- OP_FAIL,
- OP_CALL,
- OP_CONNECT,
- OP_DISCONNECT,
- OP_STARTTLS,
- OP_SLEEP,
- OP_WRITE,
-
- OP_EXPECT_DISCONNECT,
- OP_EXPECT_SMTP_RESPONSE,
-};
-
-struct op {
- struct op *next;
- int type;
- union {
- struct {
- int count;
- struct op *start;
- struct op *last;
- } block;
- struct {
- struct op *op;
- int count;
- } repeat;
- struct {
- struct op *block;
- } random;
- struct {
- char *reason;
- } fail;
- struct {
- struct procedure *proc;
- } call;
- struct {
- char *hostname;
- int portno;
- } connect;
- struct {
- unsigned int ms;
- } sleep;
- struct {
- const void *buf;
- size_t len;
- } write;
- struct {
- int flags;
- } expect_smtp;
- } u;
-};
-
-#define RES_OK 0
-#define RES_SKIP 1
-#define RES_FAIL 2
-#define RES_ERROR 3
-
-struct ctx {
- int sock;
- void *ssl;
- struct iobuf iobuf;
- int lvl;
-
- int result;
- char *reason;
-};
-
-static struct op * _op_connect;
-
-int verbose;
-int randomdelay; /* between each testcase */
-int tapout;
-size_t rundelay; /* between each testcase */
-
-static size_t test_pass;
-static size_t test_skip;
-static size_t test_fail;
-static size_t test_error;
-static size_t test_total = 0;
-
-static struct op *op_add_child(struct op *, const struct op *);
-static void run_testcase(struct procedure *);
-static void print_testcase(char *status, char *name, char *reason, char *directive, size_t number);
-static void process_op(struct ctx *, struct op *);
-static const char * parse_smtp_response(char *, size_t, char **, int *);
-
-struct procedure *
-procedure_create(struct script *scr, char *name)
-{
- struct procedure *p;
-
- if (procedure_get_by_name(scr, name)) {
- warnx("procedure \"%s\" already exists", name);
- return (NULL);
- }
-
- p = calloc(1, sizeof *p);
- TAILQ_INIT(&p->vars);
- p->name = strdup(name);
-
- TAILQ_INSERT_TAIL(&scr->procs, p, entry);
-
- return (p);
-}
-
-struct procedure *
-procedure_get_by_name(struct script *scr, const char *name)
-{
- struct procedure *p;
-
- TAILQ_FOREACH(p, &scr->procs, entry)
- if (!strcmp(name, p->name))
- return (p);
-
- return (NULL);
-}
-
-int
-proc_getvaridx(struct procedure *proc, char *name)
-{
- struct variable *v;
- int n;
-
- n = 0;
- TAILQ_FOREACH(v, &proc->vars, entry) {
- if (!strcmp(name, v->name))
- return (n);
- n++;
- }
-
- return (-1);
-}
-
-int
-proc_addvar(struct procedure *proc, char *name)
-{
- struct variable *v;
-
- printf("adding variable \"%s\"\n", name);
-
- if (proc_getvaridx(proc, name) != -1)
- return (-1);
- v = calloc(1, sizeof *v);
- v->name = name;
- TAILQ_INSERT_TAIL(&proc->vars, v, entry);
-
- return (proc->varcount++);
-}
-
-struct op *
-op_block(struct op *parent)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_BLOCK;
-
- return (op_add_child(parent, &o));
-}
-
-struct op *
-op_repeat(struct op *parent, int count, struct op *op)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_REPEAT;
- o.u.repeat.count = count;
- o.u.repeat.op = op;
-
- return (op_add_child(parent, &o));
-}
-
-struct op *
-op_random(struct op *parent, struct op *op)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_RANDOM;
- o.u.random.block = op;
-
- return (op_add_child(parent, &o));
-}
-
-struct op *
-op_noop(struct op *parent)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_NOOP;
-
- return (op_add_child(parent, &o));
-}
-
-struct op *
-op_call(struct op *parent, struct procedure *proc)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_CALL;
- o.u.call.proc = proc;
-
- return (op_add_child(parent, &o));
-}
-
-struct op *
-op_fail(struct op *parent, char *reason)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_FAIL;
- o.u.fail.reason = reason;
-
- return (op_add_child(parent, &o));
-}
-
-struct op *
-op_connect(struct op *parent, const char *hostname, int portno)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_CONNECT;
- o.u.connect.hostname = strdup(hostname);
- o.u.connect.portno = portno;
- return (op_add_child(parent, &o));
-}
-
-struct op *
-op_disconnect(struct op *parent)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_DISCONNECT;
- return (op_add_child(parent, &o));
-}
-
-struct op *
-op_starttls(struct op *parent)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_STARTTLS;
- return (op_add_child(parent, &o));
-}
-
-struct op *
-op_sleep(struct op *parent, unsigned int ms)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_SLEEP;
- o.u.sleep.ms = ms;
- return (op_add_child(parent, &o));
-}
-
-struct op *
-op_write(struct op *parent, const void *buf, size_t len)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_WRITE;
- o.u.write.buf = buf;
- o.u.write.len = len;
- return (op_add_child(parent, &o));
-}
-
-struct op *
-op_printf(struct op *parent, const char *fmt, ...)
-{
- va_list ap;
- char *buf;
- int len;
-
- va_start(ap, fmt);
- if ((len = vasprintf(&buf, fmt, ap)) == -1)
- err(1, "vasprintf");
- va_end(ap);
-
- return op_write(parent, buf, len);
-}
-
-struct op *
-op_expect_disconnect(struct op *parent)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_EXPECT_DISCONNECT;
- return (op_add_child(parent, &o));
-}
-
-struct op *
-op_expect_smtp_response(struct op *parent, int flags)
-{
- struct op o;
-
- bzero(&o, sizeof o);
- o.type = OP_EXPECT_SMTP_RESPONSE;
- o.u.expect_smtp.flags = flags;
- return (op_add_child(parent, &o));
-}
-
-static void
-usage(void)
-{
- extern const char *__progname;
- errx(1, "Usage: %s [-rvt] [-d delay] script", __progname);
-}
-
-int
-main(int argc, char **argv)
-{
- struct script *s;
- struct procedure *p;
- int ch;
-
- while ((ch = getopt(argc, argv, "d:rvt")) != -1) {
- switch(ch) {
- case 'v':
- verbose += 1;
- break;
- case 'd':
- rundelay = atoi(optarg) * 1000;
- break;
- case 'r':
- randomdelay = 1;
- break;
- case 't':
- tapout = 1;
- break;
- default:
- usage();
- /* NOTREACHED */
- }
- }
- argc -= optind;
- argv += optind;
-
- if (argc != 1)
- usage();
-
- s = parse_script(argv[0]);
- if (s == NULL)
- errx(1, "error reading script file");
-
- _op_connect = op_connect(NULL, "127.0.0.1", 25);
-
- if (tapout) {
- printf("# smtpscript is an SMTP testing framework\n\n");
- printf("TAP version 13\n");
- }
-
- TAILQ_FOREACH(p, &s->procs, entry)
- if (p->flags & PROC_TESTCASE)
- run_testcase(p);
-
- if (tapout)
- printf("1..%zu\n", test_total);
- else {
- printf("passed: %zu/%zu (skipped: %zu, failed: %zu, error: %zu)\n",
- test_pass,
- test_total,
- test_skip,
- test_fail,
- test_error);
- }
- return (0);
-}
-
-static struct op *
-op_add_child(struct op *parent, const struct op *op)
-{
- struct op *n;
-
- n = malloc(sizeof *n);
- if (n == NULL)
- err(1, "malloc");
-
- memmove(n, op, sizeof *n);
- n->next = NULL;
-
- /* printf("op:%p type:%i parent: %p\n", n, n->type, parent); */
-
- if (parent) {
- if (parent->u.block.start == NULL)
- parent->u.block.start = n;
- if (parent->u.block.last)
- parent->u.block.last->next = n;
- parent->u.block.last = n;
- parent->u.block.count += 1;
- }
-
- return (n);
-}
-
-static void
-run_testcase(struct procedure *proc)
-{
- struct ctx c;
- uint32_t rdelay;
-
- bzero(&c, sizeof c);
- c.sock = -1;
- c.lvl = 1;
-
- if (rundelay) {
- if (randomdelay)
- rdelay = arc4random_uniform(rundelay);
- else
- rdelay = rundelay;
- usleep(rdelay);
- }
-
- fflush(stdout);
-
- if (verbose > 1)
- printf("\n");
-
- if (!(proc->flags & PROC_NOCONNECT))
- process_op(&c, _op_connect);
- process_op(&c, proc->root);
-
- if (c.sock != -1)
- close(c.sock);
- if (c.ssl)
- ssl_close(c.ssl);
- iobuf_clear(&c.iobuf);
-
- if (verbose > 1) {
- printf("# Done with test-case \"%s\": ", proc->name);
- }
-
- switch (c.result) {
- case RES_OK:
- test_total += 1;
- if (proc->flags & PROC_EXPECTFAIL) {
- print_testcase("not ok", proc->name, c.reason, "TODO", test_total); // XPass
- test_fail += 1;
- } else if (proc->flags & PROC_SKIP) {
- test_skip += 1;
- print_testcase("ok", proc->name, c.reason, "SKIP", test_total);
- }
- else {
- print_testcase("ok", proc->name, c.reason, NULL, test_total);
- test_pass += 1;
- }
-
- break;
-
- case RES_SKIP:
- test_skip += 1;
- test_total += 1;
- print_testcase("not ok", proc->name, c.reason, "SKIP", test_total);
- break;
-
- case RES_FAIL:
- test_total += 1;
- if (proc->flags & PROC_EXPECTFAIL) {
- print_testcase("not ok", proc->name, c.reason, "TODO", test_total); // XFail
- test_pass += 1;
- } else if (proc->flags & PROC_SKIP) {
- test_skip += 1;
- print_testcase("ok", proc->name, c.reason, "SKIP", test_total);
- }
- else {
- print_testcase("not ok", proc->name, c.reason, NULL, test_total);
- test_fail += 1;
- }
-
- break;
-
- case RES_ERROR:
- test_error += 1;
- test_total += 1;
- print_testcase("not ok", proc->name, c.reason, NULL, test_total);
- break;
- }
-
- if (verbose > 1) {
- printf("\n");
- }
-
-}
-
-void print_testcase(char *status, char *name, char *reason, char *directive, size_t number)
-{
- printf("%s %zu", status, number);
- if (directive)
- printf(" - %s # %s\n", name, directive);
- else
- if (reason)
- printf(" - %s # %s\n", name, reason);
- else
- printf(" - %s\n", name);
-}
-
-static size_t
-strvisx2(char *dst, const char *src, size_t srclen, int flag)
-{
- size_t n, r, i;
-
- n = strvisx(dst, src, srclen, flag);
- if (n == 0)
- return (0);
-
- r = n;
- for (i = n - 1; i; i--) {
- if (dst[i] == '\r') {
- memmove(dst + i + 2, dst + i + 1, n + 1 - i);
- dst[i+1] = 'r';
- dst[i] = '\\';
- r++;
- } else if (dst[i] == '"') {
- memmove(dst + i + 2, dst + i + 1, n + 1 - i);
- dst[i+1] = '"';
- dst[i] = '\\';
- r++;
- }
- }
-
- return (r);
-}
-
-static const char *
-show_data(const char *src, size_t len, size_t max)
-{
- static char buf[8192 + 3];
- char tmp[256];
- size_t l, n;
-
- l = len;
- if (len > 2048)
- l = 2048;
-
- buf[0] = '"';
- n = strvisx2(&buf[1], src, l, VIS_SAFE | VIS_NL | VIS_TAB | VIS_CSTYLE);
- if (n >= max) {
- snprintf(tmp, sizeof tmp, "...\" [%zu]", l);
- buf[max - strlen(tmp)] = '\0';
- strlcat(buf, tmp, sizeof(buf));
- } else {
- strlcat(buf, "\"", sizeof(buf));
- }
-
- return (buf);
-}
-
-static void
-print_op(struct op *op, int lvl)
-{
-
-
- if (op->type == OP_BLOCK)
- return;
-
- while (lvl--)
- printf(" ");
-
- switch(op->type) {
-
- case OP_REPEAT:
- printf("=> repeat: %i\n", op->u.repeat.count);
- break;
-
- case OP_RANDOM:
- printf("=> random: %i\n", op->u.random.block->u.block.count);
- break;
-
- case OP_NOOP:
- printf("=> noop\n");
- break;
-
- case OP_FAIL:
- printf("=> fail: %s\n", op->u.fail.reason);
- break;
-
- case OP_CALL:
- printf("=> call: %s\n", op->u.call.proc->name);
- break;
-
- case OP_CONNECT:
- printf("=> connect %s:%i\n",
- op->u.connect.hostname,
- op->u.connect.portno);
- break;
-
- case OP_DISCONNECT:
- printf("=> disconnect\n");
- break;
-
- case OP_STARTTLS:
- printf("=> starttls\n");
- break;
-
- case OP_SLEEP:
- printf("=> sleep %ims\n", op->u.sleep.ms);
- break;
-
- case OP_WRITE:
- printf("=> write %s\n",
- show_data(op->u.write.buf, op->u.write.len, 70));
- break;
-
- case OP_EXPECT_DISCONNECT:
- printf("<= disconnect\n");
- break;
-
- case OP_EXPECT_SMTP_RESPONSE:
- printf("<= smtp-response 0x%04x\n", op->u.expect_smtp.flags);
- break;
-
- default:
- printf("<> ??? %i;\n", op->type);
- break;
- }
-}
-
-
-static void
-set_failure(struct ctx *ctx, int res, const char *fmt, ...)
-{
- va_list ap;
- int len;
-
- ctx->result = res;
- va_start(ap, fmt);
- if ((len = vasprintf(&ctx->reason, fmt, ap)) == -1)
- err(1, "vasprintf");
- va_end(ap);
-}
-
-static void
-process_op(struct ctx *ctx, struct op *op)
-{
- struct addrinfo hints, *a, *ai;
- struct op *o;
- struct iobuf *iobuf;
- int i, r, s, save_errno, cont;
- const char *cause;
- char buf[16], *servname, *line;
- ssize_t n;
- size_t len;
- const char *e;
-
- if (verbose > 1)
- print_op(op, ctx->lvl);
-
- iobuf = &ctx->iobuf;
-
- switch(op->type) {
-
- case OP_BLOCK:
- ctx->lvl += 1;
- for (o = op->u.block.start; o; o = o->next) {
- process_op(ctx, o);
- if (ctx->result)
- break;
- }
- ctx->lvl -= 1;
- break;
-
- case OP_REPEAT:
- ctx->lvl += 1;
- for (i = 0; i < op->u.repeat.count; i++) {
- process_op(ctx, op->u.repeat.op);
- if (ctx->result)
- break;
- }
- ctx->lvl -= 1;
- break;
-
- case OP_RANDOM:
-
- if (op->u.random.block->u.block.count == 0)
- return;
-
- ctx->lvl += 1;
-
- i = arc4random_uniform(op->u.random.block->u.block.count);
- for (o = op->u.random.block->u.block.start; i; i--, o = o->next)
- ;
- process_op(ctx, o);
- if (ctx->result)
- break;
- ctx->lvl -= 1;
- break;
-
- case OP_NOOP:
- break;
-
- case OP_FAIL:
- set_failure(ctx, RES_FAIL, op->u.fail.reason);
- break;
-
- case OP_CALL:
- process_op(ctx, op->u.call.proc->root);
- break;
-
- case OP_CONNECT:
- if (ctx->sock != -1)
- close(ctx->sock);
- ctx->sock = -1;
- iobuf_clear(iobuf);
-
- servname = NULL;
- if (op->u.connect.portno) {
- snprintf(buf, sizeof buf, "%i", op->u.connect.portno);
- servname = buf;
- }
- bzero(&hints, sizeof hints);
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- r = getaddrinfo(op->u.connect.hostname, servname, &hints, &ai);
- if (r) {
- set_failure(ctx, RES_ERROR,
- "failed to connect to %s:%s: %s",
- op->u.connect.hostname, servname, gai_strerror(r));
- return;
- }
-
- s = -1;
- for(a = ai; a; a = a->ai_next) {
- s = socket(a->ai_family, a->ai_socktype, a->ai_protocol);
- if (s == -1) {
- cause = "socket";
- continue;
- }
- if (connect(s, a->ai_addr, a->ai_addrlen) == -1) {
- cause = "connect";
- save_errno = errno;
- close(s);
- errno = save_errno;
- s = -1;
- continue;
- }
- break; /* okay we got one */
- }
- freeaddrinfo(ai);
- if (s == -1) {
- set_failure(ctx, RES_ERROR,
- "failed to connect to %s:%s: %s",
- op->u.connect.hostname, servname, cause);
- } else {
- ctx->sock = s;
- iobuf_init(iobuf, 0, 0);
- }
- break;
-
- case OP_DISCONNECT:
- if (ctx->sock != -1)
- close(ctx->sock);
- ctx->sock = -1;
- iobuf_clear(iobuf);
- break;
-
- case OP_STARTTLS:
- if (ctx->ssl)
- set_failure(ctx, RES_ERROR, "SSL context already here");
- else if ((ctx->ssl = ssl_connect(ctx->sock)) == NULL)
- set_failure(ctx, RES_ERROR, "SSL connection failed");
- break;
-
- case OP_SLEEP:
- usleep(op->u.sleep.ms * 1000);
- break;
-
- case OP_WRITE:
- iobuf_queue(iobuf, op->u.write.buf, op->u.write.len);
- if (ctx->ssl)
- r = iobuf_flush_ssl(iobuf, ctx->ssl);
- else
- r = iobuf_flush(iobuf, ctx->sock);
- switch (r) {
- case 0:
- break;
- case IOBUF_CLOSED:
- set_failure(ctx, RES_FAIL, "connection closed");
- break;
- case IOBUF_WANT_WRITE:
- set_failure(ctx, RES_ERROR, "iobuf_write(): WANT_WRITE");
- break;
- case IOBUF_ERROR:
- set_failure(ctx, RES_ERROR, "IO error");
- break;
- case IOBUF_SSLERROR:
- set_failure(ctx, RES_ERROR, "SSL error");
- break;
- default:
- set_failure(ctx, RES_ERROR, "iobuf_write(): bad value");
- break;
- }
- break;
-
- case OP_EXPECT_DISCONNECT:
- if (iobuf_len(iobuf)) {
- set_failure(ctx, RES_ERROR, "%zu bytes of input left",
- iobuf_len(iobuf));
- break;
- }
- if (ctx->ssl)
- n = iobuf_read_ssl(iobuf, ctx->ssl);
- else
- n = iobuf_read(iobuf, ctx->sock);
- switch (n) {
- case IOBUF_CLOSED:
- close(ctx->sock);
- ctx->sock = -1;
- if (ctx->ssl)
- ssl_close(ctx->ssl);
- break;
- case IOBUF_WANT_READ:
- set_failure(ctx, RES_ERROR, "iobuf_read(): WANT_READ");
- break;
- case IOBUF_ERROR:
- set_failure(ctx, RES_ERROR, "IO error");
- break;
- case IOBUF_SSLERROR:
- set_failure(ctx, RES_ERROR, "SSL error");
- break;
- default:
- set_failure(ctx, RES_FAIL, "data read: %s",
- show_data(iobuf_data(iobuf), iobuf_len(iobuf), 70));
- break;
- }
- break;
-
- case OP_EXPECT_SMTP_RESPONSE:
- line = NULL;
- while (1) {
- line = iobuf_getline(iobuf, &len);
- if (line) {
- e = parse_smtp_response(line, len, NULL, &cont);
- if (e) {
- set_failure(ctx, RES_FAIL, e);
- return;
- }
- if (!cont) {
- iobuf_normalize(iobuf);
- break;
- }
- if (!(op->u.expect_smtp.flags
- & RESP_SMTP_MULTILINE)) {
- set_failure(ctx, RES_FAIL,
- "single line response expected");
- return;
- }
- continue;
- }
-
- if (iobuf_len(iobuf) >= SMTP_LINE_MAX) {
- set_failure(ctx, RES_FAIL, "line too long");
- return;
- }
-
- iobuf_normalize(iobuf);
-
- again:
- if (ctx->ssl)
- n = iobuf_read_ssl(iobuf, ctx->ssl);
- else
- n = iobuf_read(iobuf, ctx->sock);
- switch (n) {
- case IOBUF_CLOSED:
- set_failure(ctx, RES_FAIL, "connection closed");
- return;
- case IOBUF_WANT_READ:
- goto again;
- case IOBUF_ERROR:
- set_failure(ctx, RES_ERROR, "io error");
- return;
- case IOBUF_SSLERROR:
- set_failure(ctx, RES_ERROR, "SSL error");
- return;
- default:
- break;
- }
- }
-
- /* got our response */
-
- if (verbose > 1) {
- len = ctx->lvl;
- while (len--)
- printf(" ");
- printf(" >>> %s\n", show_data(line, strlen(line), 70));
- }
-
- switch (line[0]) {
- case '2':
- case '3':
- if (!(op->u.expect_smtp.flags & RESP_SMTP_OK))
- set_failure(ctx, RES_FAIL,
- "unexpected response code0: %s", line);
- break;
- case '4':
- if (!(op->u.expect_smtp.flags & RESP_SMTP_TEMPFAIL))
- set_failure(ctx, RES_FAIL,
- "unexpected response code1: %s", line);
- break;
- case '5':
- if (!(op->u.expect_smtp.flags & RESP_SMTP_PERMFAIL))
- set_failure(ctx, RES_FAIL,
- "unexpected response code2: %s", line);
- break;
- default:
- set_failure(ctx, RES_FAIL,
- "unexpected response code???: %s", line);
- break;
- }
- break;
-
- default:
- ctx->result = RES_ERROR;
- ctx->reason = "invalid operator";
- break;
- }
-}
-
-static const char *
-parse_smtp_response(char *line, size_t len, char **msg, int *cont)
-{
- size_t i;
-
- if (len >= SMTP_LINE_MAX)
- return "line too long";
-
- if (len > 3) {
- if (msg)
- *msg = line + 4;
- if (cont)
- *cont = (line[3] == '-');
- } else if (len == 3) {
- if (msg)
- *msg = line + 3;
- if (cont)
- *cont = 0;
- } else
- return "line too short";
-
- /* validate reply code */
- if (line[0] < '2' || line[0] > '5' || !isdigit(line[1]) ||
- !isdigit(line[2]))
- return "reply code out of range";
-
- /* validate reply message */
- for (i = 0; i < len; i++)
- if (!isprint(line[i]))
- return "non-printable character in reply";
-
- return NULL;
-}
diff --git a/smtpscript/smtpscript.h b/smtpscript/smtpscript.h
deleted file mode 100644
index ba90b240..00000000
--- a/smtpscript/smtpscript.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* $OpenBSD: iobuf.h,v 1.1 2012/01/29 00:32:51 eric Exp $ */
-/*
- * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
- *
- * 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.
- */
-
-struct op;
-
-#define PROC_TESTCASE 0x0001
-#define PROC_SKIP 0x0002
-#define PROC_EXPECTFAIL 0x0004
-#define PROC_NOCONNECT 0x0008
-
-
-struct variable {
- TAILQ_ENTRY(variable) entry;
- char *name;
-};
-
-struct procedure {
- int flags;
-
- TAILQ_ENTRY(procedure) entry;
- char *name;
-
- TAILQ_HEAD(, variable) vars;
- int varcount;
-
- struct op *root;
-
- int skip;
- int expect_fail;
-};
-
-#define RESP_SMTP_OK 0x0001
-#define RESP_SMTP_TEMPFAIL 0x0002
-#define RESP_SMTP_PERMFAIL 0x0004
-#define RESP_SMTP_ANY 0x0007
-
-#define RESP_SMTP_MULTILINE 0x0100
-
-struct script {
- TAILQ_HEAD(, procedure) procs;
-};
-
-int proc_addvar(struct procedure *, char *name);
-int proc_getvaridx(struct procedure *, char *name);
-
-struct op *op_block(struct op *);
-struct op *op_repeat(struct op *, int, struct op *);
-struct op *op_random(struct op *, struct op *);
-struct op *op_noop(struct op *);
-struct op *op_fail(struct op *, char *);
-struct op *op_call(struct op *, struct procedure *);
-struct op *op_connect(struct op *, const char *, int);
-struct op *op_disconnect(struct op *);
-struct op *op_starttls(struct op *);
-struct op *op_sleep(struct op *, unsigned int);
-struct op *op_write(struct op *, const void *, size_t);
-struct op *op_printf(struct op *, const char *, ...);
-
-struct op *op_expect_disconnect(struct op *);
-struct op *op_expect_smtp_response(struct op *, int);
-
-struct procedure *procedure_create(struct script *, char *);
-struct procedure *procedure_get_by_name(struct script *, const char *);
-
-struct script * parse_script(const char *);
diff --git a/smtpscript/smtpscript/Makefile b/smtpscript/smtpscript/Makefile
deleted file mode 100644
index 0520606f..00000000
--- a/smtpscript/smtpscript/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-.PATH: ${.CURDIR}/..
-
-PROG= smtpscript
-SRCS= smtpscript.c iobuf.c parse.y ssl.c
-NOMAN= noman
-
-LDADD+= -lutil -lssl -lcrypto
-DPADD+= ${LIBEVENT} ${LIBUTIL} ${LIBSSL} ${LIBCRYPTO}
-CPPFLAGS+= -I${.CURDIR}/..
-CPPFLAGS+= -DIO_TLS
-
-.include <bsd.prog.mk>
diff --git a/smtpscript/ssl.c b/smtpscript/ssl.c
deleted file mode 100644
index 54f0993d..00000000
--- a/smtpscript/ssl.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/* $OpenBSD: ssl.c,v 1.50 2012/11/12 14:58:53 eric Exp $ */
-
-/*
- * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
- * Copyright (c) 2008 Reyk Floeter <reyk@openbsd.org>
- *
- * 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.
- */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/tree.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <event.h>
-#include <fcntl.h>
-#include <imsg.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <openssl/ssl.h>
-#include <openssl/engine.h>
-#include <openssl/err.h>
-
-#define SSL_CIPHERS "HIGH"
-
-void ssl_error(const char *);
-
-static void ssl_init(void);
-static SSL_CTX *ssl_ctx_create(void);
-static void *ssl_client_ctx(void);
-
-static void
-ssl_init(void)
-{
- static int init = 0;
-
- if (init)
- return;
-
- init = 1;
-
- SSL_library_init();
- SSL_load_error_strings();
-
- OpenSSL_add_all_algorithms();
-
- /* Init hardware crypto engines. */
- ENGINE_load_builtin_engines();
- ENGINE_register_all_complete();
-}
-
-void
-ssl_error(const char *where)
-{
- unsigned long code;
- char errbuf[128];
-
- for (; (code = ERR_get_error()) != 0 ;) {
- ERR_error_string_n(code, errbuf, sizeof(errbuf));
- fprintf(stderr, "debug: SSL library error: %s: %s",
- where, errbuf);
- }
-}
-
-void *
-ssl_connect(int sock)
-{
- SSL *ssl;
-
- ssl = ssl_client_ctx();
-
- if (SSL_set_fd(ssl, sock) == 0) {
- ssl_error("ssl_connect:SSL_set_fd");
- SSL_free(ssl);
- return (NULL);
- }
-
- if (SSL_connect(ssl) != 1) {
- ssl_error("ssl_connect:SSL_connect");
- SSL_free(ssl);
- return (NULL);
- }
-
- return ((void*)ssl);
-}
-
-void
-ssl_close(void *a)
-{
- SSL *ssl = a;
-
- SSL_free(ssl);
-}
-
-static SSL_CTX *
-ssl_ctx_create(void)
-{
- SSL_CTX *ctx;
-
- ssl_init();
-
- ctx = SSL_CTX_new(SSLv23_method());
- if (ctx == NULL) {
- ssl_error("ssl_ctx_create");
- errx(1, "ssl_ctx_create: could not create SSL context");
- }
-
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
- SSL_CTX_set_timeout(ctx, 30);
- SSL_CTX_set_options(ctx,
- SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_TICKET);
- SSL_CTX_set_options(ctx,
- SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
-
- if (!SSL_CTX_set_cipher_list(ctx, SSL_CIPHERS)) {
- ssl_error("ssl_ctx_create");
- errx(1, "ssl_ctx_create: could not set cipher list");
- }
-
- return (ctx);
-}
-
-static void *
-ssl_client_ctx(void)
-{
- SSL_CTX *ctx;
- SSL *ssl = NULL;
- int rv = -1;
-
- ctx = ssl_ctx_create();
-
- if ((ssl = SSL_new(ctx)) == NULL)
- goto done;
- SSL_CTX_free(ctx);
-
- if (!SSL_set_ssl_method(ssl, SSLv23_client_method()))
- goto done;
-
- rv = 0;
-done:
- if (rv) {
- if (ssl)
- SSL_free(ssl);
- else if (ctx)
- SSL_CTX_free(ctx);
- ssl = NULL;
- }
- return (void*)(ssl);
-}