Commit 2c4d27f9 authored by Geoff Simmons's avatar Geoff Simmons

Initial commit -- passes 00basic.vtc, but other code is not yet tested.

00basic.vtc tests the gcrypt_version() function, which implicitly tests
initialization of libgcrypt.
parents
Pipeline #158 skipped
((nil . ((indent-tabs-mode . t)))
(c-mode . ((c-file-style . "BSD"))))
Makefile
Makefile.in
.deps/
.libs/
*.o
*.lo
*.la
*~
*.[1-9]
/aclocal.m4
/autom4te.cache/
/compile
/config.guess
/config.h
/config.h.in
/config.log
/config.status
/config.sub
/configure
/depcomp
/install-sh
/libtool
/ltmain.sh
/missing
/stamp-h1
/m4/libtool.m4
/m4/lt*.m4
/src/vcc_if.c
/src/vcc_if.h
/src/vmod_*rst
CONTRIBUTING
============
To contribute code or documentation, submit a pull request at the
`source repository website
<https://code.uplex.de/uplex-varnish/libvmod-gcrypt>`_.
If you have a problem or discover a bug, you can post an `issue
<https://code.uplex.de/uplex-varnish/libvmod-gcrypt/issues>`_ at
the website. You can also write to <varnish-support@uplex.de>.
For developers
--------------
The build specifies C99 conformance, all compiler warnings turned on,
and all warnings considered errors (compiler options ``-std=c99
-Werror -Wall -Wextra``).
The VMOD has been tested with both the gcc and clang compilers, and
should always compile and test successfully with both of them.
By default, ``CFLAGS`` is set to ``-g -O2``, so that symbols are
included in the shared library, and optimization is at level
``O2``. To change or disable these options, set ``CFLAGS`` explicitly
before calling ``make`` (it may be set to the empty string).
For development/debugging cycles, the ``configure`` option
``--enable-debugging`` is recommended (off by default). This will turn
off optimizations and function inlining, so that a debugger will step
through the code as expected.
See LICENSE for details.
INSTALLATION
============
The VMOD is built against a Varnish installation, and the autotools
use ``pkg-config(1)`` to locate the necessary header files and other
resources. This sequence will install the VMOD::
> ./autogen.sh # for builds from the git repo
> ./configure
> make
> make check # to run unit tests in src/tests/*.vtc
> sudo make install
If you have installed Varnish in a non-standard directory, call
``autogen.sh`` and ``configure`` with the ``PKG_CONFIG_PATH``
environment variable pointing to the appropriate path. For example,
when varnishd configure was called with ``--prefix=$PREFIX``, use::
> PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig
> export PKG_CONFIG_PATH
By default, the vmod ``configure`` script installs the vmod in
the same directory as Varnish, determined via ``pkg-config(1)``. The
vmod installation directory can be overridden by passing the
``VMOD_DIR`` variable to ``configure``.
Other files such as the man-page are installed in the locations
determined by ``configure``, which inherits its default ``--prefix``
setting from Varnish.
Copyright (c) 2017 UPLEX Nils Goroll Systemoptimierung
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 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.
ACLOCAL_AMFLAGS = -I m4 -I ${LIBVARNISHAPI_DATAROOTDIR}/aclocal
SUBDIRS = src
DISTCHECK_CONFIGURE_FLAGS = \
VMOD_DIR='$${libdir}/varnish/vmods'
EXTRA_DIST = README.rst LICENSE COPYING
doc_DATA = README.rst LICENSE COPYING
dist_man_MANS = vmod_gcrypt.3
MAINTAINERCLEANFILES = $(dist_man_MANS)
vmod_gcrypt.3: README.rst
README.rst: src/vmod_gcrypt.man.rst
cp src/vmod_gcrypt.man.rst README.rst
src/vmod_gcrypt.man.rst:
make -C src vmod_gcrypt.man.rst
%.1 %.2 %.3 %.4 %.5 %.6 %.7 %.8 %.9:
if HAVE_RST2MAN
${RST2MAN} $< $@
else
@echo "========================================"
@echo "You need rst2man installed to make dist"
@echo "========================================"
@false
endif
..
.. NB: This file is machine generated, DO NOT EDIT!
..
.. Edit vmod.vcc and run make instead
..
.. role:: ref(emphasis)
.. _vmod_gcrypt(3):
===========
vmod_gcrypt
===========
------------------------------------------
access the libgcrypt cryptographic library
------------------------------------------
:Manual section: 3
SYNOPSIS
========
import gcrypt [from "path"] ;
::
new OBJECT = ...
DESCRIPTION
===========
This Varnish Module (VMOD) provides access to the libgcrypt library of
cryptographic building blocks -- the same library used by the GNU
Privacy Guard cryptographic suite (GnuPG or GPG).
CONTENTS
========
* symmetric(ENUM {AES,AES128,RIJNDAEL,RIJNDAEL128,AES192,RIJNDAEL192,AES256,RIJNDAEL256}, ENUM {ECB,CFB,CBC,OFB,CTR,AESWRAP,CCM,GCM}, BLOB, BLOB, BLOB, BOOL, BOOL, BOOL, BOOL)
* STRING version()
* STRING gcrypt_version()
.. _obj_symmetric:
symmetric
---------
::
new OBJ = symmetric(ENUM {AES,AES128,RIJNDAEL,RIJNDAEL128,AES192,RIJNDAEL192,AES256,RIJNDAEL256} cipher, ENUM {ECB,CFB,CBC,OFB,CTR,AESWRAP,CCM,GCM} mode, BLOB key, BLOB iv=0, BLOB ctr=0, BOOL secure=1, BOOL enable_sync=0, BOOL cbc_cts=0, BOOL cbc_mac=0)
.. _func_symmetric.encrypt:
symmetric.encrypt
-----------------
::
BLOB symmetric.encrypt(BLOB)
.. _func_symmetric.decrypt:
symmetric.decrypt
-----------------
::
BLOB symmetric.decrypt(BLOB)
.. _func_version:
version
-------
::
STRING version()
Returns the version string for this VMOD.
Example::
std.log("Using VMOD gcrypt version " + gcrypt.version());
.. _func_gcrypt_version:
gcrypt_version
--------------
::
STRING gcrypt_version()
Returns the version string for the ``libgcrypt`` library with which
the VMOD is linked.
Example::
std.log("Using libgcrypt version " + gcrypt.gcrypt_version());
REQUIREMENTS
============
This VMOD requires Varnish ...
LIMITATIONS
===========
...
INSTALLATION
============
See `INSTALL.rst <INSTALL.rst>`_ in the source repository.
SEE ALSO
========
* varnishd(1)
* vcl(7)
* source repository: https://code.uplex.de/uplex-varnish/libvmod-gcrypt
COPYRIGHT
=========
::
This document is licensed under the same conditions
as the libvmod-gcrypt project. See LICENSE for details.
Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
#!/bin/sh
warn() {
echo "WARNING: $@" 1>&2
}
case `uname -s` in
Darwin)
LIBTOOLIZE=glibtoolize
;;
FreeBSD)
LIBTOOLIZE=libtoolize
;;
Linux)
LIBTOOLIZE=libtoolize
;;
SunOS)
LIBTOOLIZE=libtoolize
;;
*)
warn "unrecognized platform:" `uname -s`
LIBTOOLIZE=libtoolize
esac
automake_version=`automake --version | tr ' ' '\n' | egrep '^[0-9]\.[0-9a-z.-]+'`
if [ -z "$automake_version" ] ; then
warn "unable to determine automake version"
else
case $automake_version in
0.*|1.[0-8]|1.[0-8][.-]*)
warn "automake ($automake_version) detected; 1.9 or newer recommended"
;;
*)
;;
esac
fi
# check for varnishapi.m4 in custom paths
dataroot=$(pkg-config --variable=datarootdir varnishapi 2>/dev/null)
if [ -z "$dataroot" ] ; then
cat >&2 <<'EOF'
Package varnishapi was not found in the pkg-config search path.
Perhaps you should add the directory containing `varnishapi.pc'
to the PKG_CONFIG_PATH environment variable
EOF
exit 1
fi
set -ex
aclocal -I m4 -I ${dataroot}/aclocal
$LIBTOOLIZE --copy --force
autoheader
automake --add-missing --copy --foreign
autoconf
AC_PREREQ(2.59)
AC_COPYRIGHT([Copyright (c) 2017 UPLEX - Nils Goroll Systemoptimierung])
AC_INIT([VMOD gcrypt], [trunk], [varnish-support@uplex.de], [libvmod-gcrypt],
[https://code.uplex.de/uplex-varnish/libvmod-gcrypt])
AC_CONFIG_MACRO_DIR([m4])
m4_ifndef([VARNISH_VMOD_INCLUDES],
AC_MSG_ERROR([Need varnish.m4 -- see README.rst]))
AC_CONFIG_SRCDIR(src/vmod_gcrypt.vcc)
AM_CONFIG_HEADER(config.h)
AC_CANONICAL_SYSTEM
AC_LANG(C)
AM_INIT_AUTOMAKE([foreign])
AC_PROG_CC
AC_PROG_CC_C99
if test "x$ac_cv_prog_cc_c99" = xno; then
AC_MSG_ERROR([Could not find a C99 compatible compiler])
fi
AC_PROG_CPP
AX_PTHREAD(,[AC_MSG_ERROR([Could not configure pthreads support])])
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
CC="$PTHREAD_CC"
# Checks for libtool
LT_INIT([disable-static])
AC_PROG_INSTALL
AC_PROG_LIBTOOL
AC_PROG_MAKE_SET
# Checks for header files.
AC_HEADER_STDC
# Checks for C sources
# backwards compat with older pkg-config
# - pull in AC_DEFUN from pkg.m4
m4_ifndef([PKG_CHECK_VAR], [
# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# -------------------------------------------
# Retrieves the value of the pkg-config variable for the given module.
AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl
])# PKG_CHECK_VAR
])
PKG_CHECK_MODULES([libvarnishapi], [varnishapi])
PKG_CHECK_VAR([LIBVARNISHAPI_PREFIX], [varnishapi], [prefix])
PKG_CHECK_VAR([LIBVARNISHAPI_DATAROOTDIR], [varnishapi], [datarootdir])
PKG_CHECK_VAR([LIBVARNISHAPI_BINDIR], [varnishapi], [bindir])
PKG_CHECK_VAR([LIBVARNISHAPI_SBINDIR], [varnishapi], [sbindir])
AC_SUBST([LIBVARNISHAPI_DATAROOTDIR])
# Varnish include files tree
VARNISH_VMOD_INCLUDES
VARNISH_VMOD_DIR
VARNISH_VMODTOOL
# inherit the prefix from Varnish.
# acessing ac_ variable because AC_PREFIX_DEFAULT acts too early
ac_default_prefix=$LIBVARNISHAPI_PREFIX
AC_PATH_PROG([VARNISHTEST], [varnishtest], [],
[$LIBVARNISHAPI_BINDIR:$LIBVARNISHAPI_SBINDIR:$PATH])
AC_PATH_PROG([VARNISHD], [varnishd], [],
[$LIBVARNISHAPI_SBINDIR:$LIBVARNISHAPI_BINDIR:$PATH])
# Check for rst utilities
AC_CHECK_PROGS(RST2MAN, [rst2man rst2man.py], "no")
if test "x$RST2MAN" = "xno"; then
AC_MSG_WARN([rst2man not found - not building man pages])
fi
AM_CONDITIONAL(HAVE_RST2MAN, [test "x$RST2MAN" != "xno"])
AM_PATH_LIBGCRYPT([1:1.6.3], [],
[AC_MSG_ERROR([libgcrypt > 1.6.3 and API version 1 required])]
)
# --enable-stack-protector
AC_ARG_ENABLE(stack-protector,
AS_HELP_STRING([--enable-stack-protector],[enable stack protector (default is YES)]),
[],
[enable_stack_protector=yes])
if test "x$enable_stack_protector" != "xno"; then
AX_CHECK_COMPILE_FLAG([-fstack-protector],
AX_CHECK_LINK_FLAG([-fstack-protector],
[CFLAGS="${CFLAGS} -fstack-protector"], [], []),
[], [])
fi
# --enable-debugging
AC_ARG_ENABLE(debugging,
AS_HELP_STRING([--enable-debugging],[enable debugging (default is NO)]),
[],
[enable_debugging=no])
# AC_PROG_CC sets CFLAGS to '-g -O2' unless it is already set, so
# there's no need to add -g. Disable or change by explicitly setting
# CFLAGS. If this option is enabled, then -Og or -O0 becomes the last
# optimization option, and hence takes precedence.
if test "x$enable_debugging" != "xno"; then
CFLAGS="${CFLAGS} -fno-inline"
AX_CHECK_COMPILE_FLAG([-Og],
[CFLAGS="${CFLAGS} -Og"],
[CFLAGS="${CFLAGS} -O0"],
[])
fi
AC_CONFIG_FILES([
Makefile
src/Makefile
])
AC_OUTPUT
AM_CPPFLAGS = @VMOD_INCLUDES@ -Wall -Werror -Wextra -std=c99 @LIBGCRYPT_CFLAGS@
vmoddir = @VMOD_DIR@
vmod_LTLIBRARIES = libvmod_gcrypt.la
libvmod_gcrypt_la_LDFLAGS = -module -export-dynamic -avoid-version -shared
libvmod_gcrypt_la_SOURCES = \
vmod_gcrypt.c
nodist_libvmod_gcrypt_la_SOURCES = \
vcc_if.c \
vcc_if.h
libvmod_gcrypt_la_LIBADD = @LIBGCRYPT_LIBS@
vmod_gcrypt.lo: vcc_if.c vcc_if.h
vcc_if.c: vcc_if.h
vcc_if.h vmod_gcrypt.man.rst: @VMODTOOL@ $(top_srcdir)/src/vmod_gcrypt.vcc
@VMODTOOL@ $(top_srcdir)/src/vmod_gcrypt.vcc
VMOD_TESTS = $(builddir)/tests/*.vtc
.PHONY: $(VMOD_TESTS)
$(builddir)/tests/*.vtc: libvmod_gcrypt.la
PATH=@LIBVARNISHAPI_SBINDIR@:$$PATH \
@VARNISHTEST@ -Dvmod_topbuild=$(abs_top_builddir) $@
check: $(VMOD_TESTS)
EXTRA_DIST = \
vmod_gcrypt.vcc \
$(VMOD_TESTS)
CLEANFILES = \
$(builddir)/vcc_if.c \
$(builddir)/vcc_if.h \
$(builddir)/vmod_gcrypt.rst \
$(builddir)/vmod_gcrypt.man.rst
/*-
* Copyright 2017 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 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 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.
*
*/
CIPHER(AES, GCRY_CIPHER_AES)
CIPHER(AES128, GCRY_CIPHER_AES128)
CIPHER(RIJNDAEL, GCRY_CIPHER_RIJNDAEL)
CIPHER(RIJNDAEL128, GCRY_CIPHER_RIJNDAEL128)
CIPHER(AES192, GCRY_CIPHER_AES192)
CIPHER(RIJNDAEL192, GCRY_CIPHER_RIJNDAEL192)
CIPHER(AES256, GCRY_CIPHER_AES256)
CIPHER(RIJNDAEL256, GCRY_CIPHER_RIJNDAEL256)
/*-
* Copyright 2017 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 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 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.
*
*/
MODE(ECB, GCRY_CIPHER_MODE_ECB)
MODE(CFB, GCRY_CIPHER_MODE_CFB)
MODE(CBC, GCRY_CIPHER_MODE_CBC)
MODE(OFB, GCRY_CIPHER_MODE_OFB)
MODE(CTR, GCRY_CIPHER_MODE_CTR)
MODE(AESWRAP, GCRY_CIPHER_MODE_AESWRAP)
MODE(CCM, GCRY_CIPHER_MODE_CCM)
MODE(GCM, GCRY_CIPHER_MODE_GCM)
# looks like -*- vcl -*-
varnishtest "vcl.use and .discard, and version strings"
server s1 {} -start
varnish v1 -vcl+backend {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
} -start
varnish v1 -vcl+backend {}
varnish v1 -cli "vcl.list"
varnish v1 -cli "vcl.use vcl1"
varnish v1 -cli "vcl.use vcl2"
varnish v1 -cli "vcl.use vcl1"
varnish v1 -cli "vcl.show vcl1"
varnish v1 -cli "vcl.use vcl2"
varnish v1 -cli "vcl.discard vcl1"
varnish v1 -cli "vcl.list"
varnish v1 -vcl {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
backend b { .host = "${bad_ip}"; }
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.x-version = gcrypt.version();
if (!resp.http.x-version) {
set resp.status = 500;
}
set resp.http.x-gcrypt-version = gcrypt.gcrypt_version();
if (!resp.http.x-gcrypt-version) {
set resp.status = 500;
}
return(deliver);
}
}
client c1 {
txreq -url "/"
rxresp
expect resp.status == 200
expect resp.http.x-version ~ "^.+$"
expect resp.http.x-gcrypt-version ~ "^.+$"
} -run
/*-
* Copyright 2017 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 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 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.
*
*/
/* for strdup() */
#define _POSIX_C_SOURCE 200809L
#include "config.h"
#include <gcrypt.h>
#include <string.h>
#include "vcl.h"
#include "cache/cache.h"
#include "vrt.h"
#include "vas.h"
#include "vdef.h"
#include "vcc_if.h"
#define str(s) xstr(s)
#define xstr(s) #s
#define MIN_GCRYPT_VERSION "1.6.3"
#define ERR(ctx, msg) \
errmsg((ctx), "vmod gcrypt error: " msg)
#define VERR(ctx, fmt, ...) \
errmsg((ctx), "vmod gcrypt error: " fmt, __VA_ARGS__)
#define VERRNOMEM(ctx, fmt, ...) \
VERR((ctx), fmt ", out of space", __VA_ARGS__)
#define ERRNOMEM(ctx, msg) \
ERR((ctx), msg ", out of space")
#define INIT(ctx) (((ctx)->method & VCL_MET_INIT) != 0)
struct vmod_gcrypt_symmetric {
unsigned magic;
#define VMOD_GCRYPT_SYMMETRIC_MAGIC 0x82c7ffe2
gcry_cipher_hd_t *hd;
char *vcl_name;
size_t blocklen;
};
static const char *gcrypt_version = NULL;
void
errmsg(VRT_CTX, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (ctx->method == VCL_MET_INIT) {
AN(ctx->msg);
VSB_vprintf(ctx->msg, fmt, args);
VRT_handling(ctx, VCL_RET_FAIL);
}
else if (ctx->vsl)
VSLbv(ctx->vsl, SLT_VCL_Error, fmt, args);
else
/* Should this ever happen in vcl_fini() ... */
VSL(SLT_VCL_Error, 0, fmt, args);
va_end(args);
}
/* Event function */
int __match_proto__(vmod_event_f)
event(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
{
(void) ctx;
(void) priv;
if (e == VCL_EVENT_LOAD) {
gcrypt_version = gcry_check_version(MIN_GCRYPT_VERSION);
if (gcrypt_version == NULL) {
// XXX log error
return 1;
}
/* XXX other initialization */
}
return 0;
}
/* Object symmetric */
VCL_VOID
vmod_symmetric__init(VRT_CTX, struct vmod_gcrypt_symmetric **symmetricp,
const char *vcl_name, VCL_ENUM ciphers, VCL_ENUM modes,
VCL_BLOB key, VCL_BLOB iv, VCL_BLOB ctr, VCL_BOOL secure,
VCL_BOOL enable_sync, VCL_BOOL cbc_cts, VCL_BOOL cbc_mac)
{
struct vmod_gcrypt_symmetric *symmetric;
gcry_cipher_hd_t *hd = NULL;
int algo = GCRY_CIPHER_NONE, mode = GCRY_CIPHER_MODE_NONE;
unsigned int flags = 0;
gcry_error_t err = GPG_ERR_NO_ERROR;
size_t len;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(symmetricp);
AZ(*symmetricp);
AN(vcl_name);
AN(ciphers);
AN(modes);
if (key == NULL || key->priv == NULL) {
VERR(ctx, "key is NULL in %s constructor", vcl_name);
return;
}
assert(key->len >= 0);
#define CIPHER(e, m) if (strcmp(ciphers, str(e)) == 0) algo = m;
#include "ciphers.h"
#undef CIPHER
if (algo == GCRY_CIPHER_NONE)
WRONG("Illegal cipher enum");
if ((len = gcry_cipher_get_algo_keylen(algo)) == 0) {
VERR(ctx, "Cannot determine key length for %s cipher in %s "
"constructor", ciphers, vcl_name);
return;
}
if ((unsigned)key->len > len) {
VERR(ctx, "Key length %d is longer than the maximum supported "
"length %zu for %s cipher in %s constructor", key->len,
len, ciphers, vcl_name);
return;
}
if ((len = gcry_cipher_get_algo_blklen(algo)) == 0) {
VERR(ctx, "Cannot determine block length for %s cipher in %s "
"constructor", ciphers, vcl_name);
return;
}
#define MODE(e, m) if (strcmp(modes, str(e)) == 0) mode = m;
#include "modes.h"
#undef MODE
if (mode == GCRY_CIPHER_MODE_NONE)
WRONG("Illegal mode enum");
if (secure)
flags |= GCRY_CIPHER_SECURE;
if (enable_sync)
flags |= GCRY_CIPHER_ENABLE_SYNC;
if (cbc_cts)
flags |= GCRY_CIPHER_CBC_CTS;
if (cbc_mac)
flags |= GCRY_CIPHER_CBC_MAC;
if ((err = gcry_cipher_open(hd, algo, mode, flags))
!= GPG_ERR_NO_ERROR) {
VERR(ctx, "Cannot open cipher in %s constructor: %s/%s",
vcl_name, gcry_strsource(err), gcry_strerror(err));
return;
}
if ((err = gcry_cipher_setkey(*hd, key->priv, key->len))
!= GPG_ERR_NO_ERROR) {
VERR(ctx, "Cannot set key in %s constructor: %s/%s",
vcl_name, gcry_strsource(err), gcry_strerror(err));
return;
}
if (iv != NULL && iv->priv != NULL) {
assert(iv->len >= 0);
if ((err = gcry_cipher_setiv(*hd, iv->priv, iv->len))
!= GPG_ERR_NO_ERROR) {
VERR(ctx, "Cannot set initialization vector in %s "
"constructor: %s/%s", vcl_name,
gcry_strsource(err), gcry_strerror(err));
return;
}
}
if (ctr != NULL && ctr->priv != NULL) {
assert(ctr->len >= 0);
if ((err = gcry_cipher_setctr(*hd, ctr->priv, ctr->len))
!= GPG_ERR_NO_ERROR) {
VERR(ctx, "Cannot set counter vector in %s "
"constructor: %s/%s", vcl_name,
gcry_strsource(err), gcry_strerror(err));
return;
}
}
ALLOC_OBJ(symmetric, VMOD_GCRYPT_SYMMETRIC_MAGIC);
AN(symmetric);
*symmetricp = symmetric;
symmetric->hd = hd;
symmetric->vcl_name = strdup(vcl_name);
AN(symmetric->vcl_name);
symmetric->blocklen = len;
}
VCL_VOID
vmod_symmetric__fini(struct vmod_gcrypt_symmetric **symmetricp)
{
struct vmod_gcrypt_symmetric *symmetric;
if (symmetricp == NULL)
return;
symmetric = *symmetricp;
if (symmetric == NULL)
return;
CHECK_OBJ(symmetric, VMOD_GCRYPT_SYMMETRIC_MAGIC);
if (symmetric->vcl_name != NULL)
free(symmetric->vcl_name);
gcry_cipher_close(*symmetric->hd);
FREE_OBJ(symmetric);
}
VCL_BLOB
vmod_symmetric_encrypt(VRT_CTX, struct vmod_gcrypt_symmetric *symmetric,
VCL_BLOB plaintext)
{
size_t len;
uintptr_t snap;
struct vmod_priv *ciphertext;
gcry_error_t err = GPG_ERR_NO_ERROR;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(symmetric, VMOD_GCRYPT_SYMMETRIC_MAGIC);
if (plaintext == NULL || plaintext->priv == NULL) {
VERR(ctx, "Plaintext BLOB is NULL in %s.encrypt",
symmetric->vcl_name);
return NULL;
}
snap = WS_Snapshot(ctx->ws);
if ((ciphertext = WS_Alloc(ctx->ws, sizeof(*ciphertext))) == NULL) {
VERRNOMEM(ctx, "Allocating BLOB result in %s.encrypt",
symmetric->vcl_name);
return NULL;
}
/* XXX? depends on mode? */
len = plaintext->len + symmetric->blocklen
- (plaintext->len % symmetric->blocklen);
if ((ciphertext->priv = WS_Alloc(ctx->ws, len)) == NULL) {
VERRNOMEM(ctx, "Allocating ciphertext result in %s.encrypt",
symmetric->vcl_name);
WS_Reset(ctx->ws, snap);
return NULL;
}
if ((err = gcry_cipher_encrypt(*symmetric->hd, ciphertext->priv,
len, plaintext->priv, plaintext->len))
!= GPG_ERR_NO_ERROR) {
VERR(ctx, "in %s.encrypt: %s/%s", symmetric->vcl_name,
gcry_strsource(err), gcry_strerror(err));
WS_Reset(ctx->ws, snap);
return NULL;
}
ciphertext->len = len;
ciphertext->free = NULL;
return ciphertext;
}
VCL_BLOB
vmod_symmetric_decrypt(VRT_CTX, struct vmod_gcrypt_symmetric *symmetric,
VCL_BLOB ciphertext)
{
uintptr_t snap;
struct vmod_priv *plaintext;
gcry_error_t err = GPG_ERR_NO_ERROR;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(symmetric, VMOD_GCRYPT_SYMMETRIC_MAGIC);
if (ciphertext == NULL || ciphertext->priv == NULL) {
VERR(ctx, "Ciphertext BLOB is NULL in %s.decrypt",
symmetric->vcl_name);
return NULL;
}
snap = WS_Snapshot(ctx->ws);
if ((plaintext = WS_Alloc(ctx->ws, sizeof(*plaintext))) == NULL) {
VERRNOMEM(ctx, "Allocating BLOB result in %s.decrypt",
symmetric->vcl_name);
return NULL;
}
if ((plaintext->priv = WS_Alloc(ctx->ws, ciphertext->len)) == NULL) {
VERRNOMEM(ctx, "Allocating plaintext result in %s.decrypt",
symmetric->vcl_name);
WS_Reset(ctx->ws, snap);
return NULL;
}
if ((err = gcry_cipher_decrypt(*symmetric->hd, plaintext->priv,
ciphertext->len, ciphertext->priv,
ciphertext->len))
!= GPG_ERR_NO_ERROR) {
VERR(ctx, "in %s.decrypt: %s/%s", symmetric->vcl_name,
gcry_strsource(err), gcry_strerror(err));
WS_Reset(ctx->ws, snap);
return NULL;
}
plaintext->len = ciphertext->len;
plaintext->free = NULL;
return plaintext;
}
VCL_STRING
vmod_version(VRT_CTX __attribute__((unused)))
{
return VERSION;
}
VCL_STRING
vmod_gcrypt_version(VRT_CTX __attribute__((unused)))
{
AN(gcrypt_version);
return gcrypt_version;
}
#-
# This document is licensed under the same conditions
# as the libvmod-gcrypt project. See LICENSE for details.
#
# Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
#
$Module gcrypt 3 access the libgcrypt cryptographic library
::
new OBJECT = ...
DESCRIPTION
===========
This Varnish Module (VMOD) provides access to the libgcrypt library of
cryptographic building blocks -- the same library used by the GNU
Privacy Guard cryptographic suite (GnuPG or GPG).
$Object symmetric(ENUM {AES, AES128, RIJNDAEL, RIJNDAEL128, AES192, RIJNDAEL192,
AES256, RIJNDAEL256} cipher, ENUM {ECB, CFB, CBC, OFB, CTR,
AESWRAP, CCM, GCM} mode, BLOB key, BLOB iv=0, BLOB ctr=0,
BOOL secure=1, BOOL enable_sync=0, BOOL cbc_cts=0,
BOOL cbc_mac=0)
$Method BLOB .encrypt(BLOB)
$Method BLOB .decrypt(BLOB)
$Function STRING version()
Returns the version string for this VMOD.
Example::
std.log("Using VMOD gcrypt version " + gcrypt.version());
$Function STRING gcrypt_version()
Returns the version string for the ``libgcrypt`` library with which
the VMOD is linked.
Example::
std.log("Using libgcrypt version " + gcrypt.gcrypt_version());
REQUIREMENTS
============
This VMOD requires Varnish ...
LIMITATIONS
===========
...
INSTALLATION
============
See `INSTALL.rst <INSTALL.rst>`_ in the source repository.
SEE ALSO
========
* varnishd(1)
* vcl(7)
* source repository: https://code.uplex.de/uplex-varnish/libvmod-gcrypt
$Event event
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment