summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2013-04-05 12:08:49 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2013-04-05 12:08:49 +0200
commit0cee769fcdc9716ccb2a60b6473062a60f640bb3 (patch)
tree72205eed0e6d570bda683cdbbc37d17a0f3a21aa
parent0f87c631e7eac2ccbd36cd875d64de29dd7c714c (diff)
downloadrsyslog-0cee769fcdc9716ccb2a60b6473062a60f640bb3.tar.gz
rsyslog-0cee769fcdc9716ccb2a60b6473062a60f640bb3.tar.bz2
rsyslog-0cee769fcdc9716ccb2a60b6473062a60f640bb3.zip
log encryption: initial PoC implementation
rough baseline, needs to be extended for actual use.
-rw-r--r--configure.ac2
-rw-r--r--runtime/Makefile.am22
-rw-r--r--runtime/cryprov.h41
-rw-r--r--runtime/libgcry.c224
-rw-r--r--runtime/libgcry.h47
-rw-r--r--runtime/lmcry_gcry.c224
-rw-r--r--runtime/lmcry_gcry.h39
-rw-r--r--runtime/rsyslog.h1
-rw-r--r--runtime/stream.c27
-rw-r--r--runtime/stream.h11
-rw-r--r--tools/Makefile.am2
-rw-r--r--tools/omfile.c71
12 files changed, 701 insertions, 10 deletions
diff --git a/configure.ac b/configure.ac
index d6d4c203..0ec29f0d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -785,7 +785,7 @@ if test "x$enable_libgcrypt" = "xyes"; then
)
AC_DEFINE([ENABLE_LIBGCRYPT], [1], [Indicator that LIBGCRYPT is present])
fi
-AM_CONDITIONAL(ENABLE_GNUTLS, test x$enable_gnutls = xyes)
+AM_CONDITIONAL(ENABLE_LIBGCRYPT, test x$enable_libgcrypt = xyes)
# support for building the rsyslogd runtime
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index c05cc773..be68ce60 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -96,12 +96,12 @@ librsyslog_la_SOURCES = \
#
if WITH_MODDIRS
-librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/:$(moddirs)\" $(PTHREADS_CFLAGS) $(LIBEE_CFLAGS) -I\$(top_srcdir)/tools
+librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/:$(moddirs)\" $(PTHREADS_CFLAGS) $(LIBEE_CFLAGS) $(LIBGCRYPT_CFLAGS) -I\$(top_srcdir)/tools
else
-librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/\" -I$(top_srcdir) $(PTHREADS_CFLAGS) $(LIBEE_CFLAGS) -I\$(top_srcdir)/tools -I\$(top_srcdir)/grammar
+librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/\" -I$(top_srcdir) $(PTHREADS_CFLAGS) $(LIBEE_CFLAGS) $(LIBGCRYPT_CFLAGS) -I\$(top_srcdir)/tools -I\$(top_srcdir)/grammar
endif
#librsyslog_la_LDFLAGS = -module -avoid-version
-librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS) $(LIBEE_LIBS)
+librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS) $(LIBGCRYPT_LIBS) $(LIBEE_LIBS)
#
# regular expression support
@@ -175,6 +175,22 @@ lmnsd_gtls_la_LIBADD = $(GNUTLS_LIBS)
endif
#
+# support library for libgcrypt
+#
+if ENABLE_LIBGCRYPT
+#noinst_LTLIBRARIES += libgcry.la
+#libgcry_la_SOURCES = libgcry.c libgcry.h
+#libcgry_la_CPPFLAGS = $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS)
+ pkglib_LTLIBRARIES += lmcry_gcry.la
+ lmcry_gcry_la_SOURCES = lmcry_gcry.c lmcry_gcry.h libgcry.c libgcry.h
+ lmcry_gcry_la_CPPFLAGS = $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS)
+ lmcry_gcry_la_LDFLAGS = -module -avoid-version
+#lmcry_gcry_la_LIBADD = libgcry.la $(LIBGCRYPT_LIBS)
+ lmcry_gcry_la_LIBADD = $(LIBGCRYPT_LIBS)
+endif
+
+
+#
# support library for guardtime
#
if ENABLE_GUARDTIME
diff --git a/runtime/cryprov.h b/runtime/cryprov.h
new file mode 100644
index 00000000..c5ee95a0
--- /dev/null
+++ b/runtime/cryprov.h
@@ -0,0 +1,41 @@
+/* The interface definition for (file) crypto providers.
+ *
+ * This is just an abstract driver interface, which needs to be
+ * implemented by concrete classes.
+ *
+ * Copyright 2013 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_CRYPROV_H
+#define INCLUDED_CRYPROV_H
+
+#include <gcrypt.h>
+
+/* interface */
+BEGINinterface(cryprov) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(void *ppThis);
+ rsRetVal (*SetCnfParam)(void *ppThis, struct nvlst *lst);
+ rsRetVal (*Destruct)(void *ppThis);
+ rsRetVal (*OnFileOpen)(void *pThis, uchar *fn, void *pFileInstData);
+ rsRetVal (*Encrypt)(void *pFileInstData, uchar *buf, size_t *lenBuf);
+ rsRetVal (*OnFileClose)(void *pFileInstData);
+ENDinterface(cryprov)
+#define cryprovCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+rsRetVal initCrypt(int gcry_mode, char * iniVector);
+rsRetVal doCrypt(char *buf, size_t *len);
+#endif /* #ifndef INCLUDED_CRYPROV_H */
diff --git a/runtime/libgcry.c b/runtime/libgcry.c
new file mode 100644
index 00000000..8184c160
--- /dev/null
+++ b/runtime/libgcry.c
@@ -0,0 +1,224 @@
+/* gcry.c - rsyslog's libgcrypt based crypto provider
+ *
+ * Copyright 2013 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdio.h>
+#include <gcrypt.h>
+
+#include "rsyslog.h"
+#include "libgcry.h"
+
+
+static inline gcryfile
+gcryfileConstruct(gcryctx ctx)
+{
+ gcryfile gf;
+ if((gf = calloc(1, sizeof(struct gcryfile_s))) == NULL)
+ goto done;
+ gf->ctx = ctx;
+done: return gf;
+}
+gcryctx
+gcryCtxNew(void)
+{
+ gcryctx ctx;
+ ctx = calloc(1, sizeof(struct gcryctx_s));
+ return ctx;
+}
+
+int
+gcryfileDestruct(gcryfile gf)
+{
+ int r = 0;
+ if(gf == NULL)
+ goto done;
+
+ free(gf);
+done: return r;
+}
+void
+rsgcryCtxDel(gcryctx ctx)
+{
+ if(ctx != NULL) {
+ free(ctx);
+ }
+}
+
+static inline void
+addPadding(gcryfile pF, uchar *buf, size_t *plen)
+{
+ unsigned i;
+ size_t nPad;
+ nPad = (pF->blkLength - *plen % pF->blkLength) % pF->blkLength;
+ dbgprintf("DDDD: addPadding %d chars, blkLength %d, mod %d, pad %d\n",
+ *plen, pF->blkLength, *plen % pF->blkLength, nPad);
+ for(i = 0 ; i < nPad ; ++i)
+ buf[(*plen)+i] = 0x00;
+ (*plen)+= nPad;
+}
+
+static inline void
+removePadding(char *buf, size_t *plen)
+{
+ unsigned len = (unsigned) *plen;
+ unsigned iSrc, iDst;
+ char *frstNUL;
+
+ frstNUL = strchr(buf, 0x00);
+ if(frstNUL == NULL)
+ goto done;
+ iDst = iSrc = frstNUL - buf;
+
+ while(iSrc < len) {
+ if(buf[iSrc] != 0x00)
+ buf[iDst++] = buf[iSrc];
+ ++iSrc;
+ }
+
+ *plen = iDst;
+done: return;
+}
+
+rsRetVal
+rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, int gcry_mode, char *iniVector)
+{
+ #define GCRY_CIPHER GCRY_CIPHER_3DES // TODO: make configurable
+ size_t keyLength;
+ char *aesSymKey = "123456789012345678901234"; // TODO: TEST ONLY
+ gcry_error_t gcryError;
+ gcryfile gf = NULL;
+ DEFiRet;
+
+ CHKmalloc(gf = gcryfileConstruct(ctx));
+
+ gf->blkLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER);
+ keyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER);
+
+ gcryError = gcry_cipher_open(
+ &gf->chd, // gcry_cipher_hd_t *
+ GCRY_CIPHER, // int
+ gcry_mode, // int
+ 0); // unsigned int
+ if (gcryError) {
+ dbgprintf("gcry_cipher_open failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ gcryError = gcry_cipher_setkey(gf->chd, aesSymKey, keyLength);
+ if (gcryError) {
+ dbgprintf("gcry_cipher_setkey failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ gcryError = gcry_cipher_setiv(gf->chd, iniVector, gf->blkLength);
+ if (gcryError) {
+ dbgprintf("gcry_cipher_setiv failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ *pgf = gf;
+finalize_it:
+ if(iRet != RS_RET_OK && gf != NULL)
+ gcryfileDestruct(gf);
+ RETiRet;
+}
+
+int
+rsgcryEncrypt(gcryfile pF, uchar *buf, size_t *len)
+{
+ int gcryError;
+ DEFiRet;
+
+ if(*len == 0)
+ FINALIZE;
+
+ addPadding(pF, buf, len);
+ gcryError = gcry_cipher_encrypt(pF->chd, buf, *len, NULL, 0);
+ if(gcryError) {
+ dbgprintf("gcry_cipher_encrypt failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* module-init dummy for potential later use */
+int
+rsgcryInit(void)
+{
+ return 0;
+}
+
+/* module-deinit dummy for potential later use */
+void
+rsgcryExit(void)
+{
+ return;
+}
+
+#if 0 // we use this for the tool, only!
+static void
+doDeCrypt(FILE *fpin, FILE *fpout)
+{
+ gcry_error_t gcryError;
+ char buf[64*1024];
+ size_t nRead, nWritten;
+ size_t nPad;
+
+ while(1) {
+ nRead = fread(buf, 1, sizeof(buf), fpin);
+ if(nRead == 0)
+ break;
+ nPad = (blkLength - nRead % blkLength) % blkLength;
+ fprintf(stderr, "read %d chars, blkLength %d, mod %d, pad %d\n", nRead, blkLength,
+ nRead % blkLength, nPad);
+ gcryError = gcry_cipher_decrypt(
+ gcryCipherHd, // gcry_cipher_hd_t
+ buf, // void *
+ nRead, // size_t
+ NULL, // const void *
+ 0); // size_t
+ if (gcryError) {
+ fprintf(stderr, "gcry_cipher_encrypt failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ return;
+ }
+fprintf(stderr, "in remove pad, %d\n", nRead);
+ removePadding(buf, &nRead);
+fprintf(stderr, "out remove pad %d\n", nRead);
+ nWritten = fwrite(buf, 1, nRead, fpout);
+ if(nWritten != nRead) {
+ perror("fpout");
+ return;
+ }
+ }
+}
+#endif
diff --git a/runtime/libgcry.h b/runtime/libgcry.h
new file mode 100644
index 00000000..0405162f
--- /dev/null
+++ b/runtime/libgcry.h
@@ -0,0 +1,47 @@
+/* libgcry.h - rsyslog's guardtime support library
+ *
+ * Copyright 2013 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_LIBGCRY_H
+#define INCLUDED_LIBGCRY_H
+#include <gt_base.h>
+
+
+struct gcryctx_s {
+ void *usrptr; /* for error function */
+};
+typedef struct gcryctx_s *gcryctx;
+typedef struct gcryfile_s *gcryfile;
+
+/* this describes a file, as far as libgcry is concerned */
+struct gcryfile_s {
+ gcry_cipher_hd_t chd; /* cypher handle */
+ size_t blkLength; /* size of low-level crypto block */
+ gcryctx ctx;
+};
+
+int rsgcryInit(void);
+void rsgcryExit(void);
+gcryctx gcryCtxNew(void);
+void rsgcryCtxDel(gcryctx ctx);
+int gcryfileDestruct(gcryfile gf);
+rsRetVal rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, int gcry_mode, char * iniVector);
+int rsgcryEncrypt(gcryfile pF, uchar *buf, size_t *len);
+
+#endif /* #ifndef INCLUDED_LIBGCRY_H */
diff --git a/runtime/lmcry_gcry.c b/runtime/lmcry_gcry.c
new file mode 100644
index 00000000..6800055d
--- /dev/null
+++ b/runtime/lmcry_gcry.c
@@ -0,0 +1,224 @@
+/* lmcry_gcry.c
+ *
+ * An implementation of the cryprov interface for libgcrypt.
+ *
+ * Copyright 2013 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "cryprov.h"
+#include "libgcry.h"
+#include "lmcry_gcry.h"
+
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
+
+/* tables for interfacing with the v6 config system */
+static struct cnfparamdescr cnfpdescr[] = {
+ { "cry.mode", eCmdHdlrGetWord, 0 }, /* CBC, ECB, etc */
+ { "cry.algo", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk pblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(cnfpdescr)/sizeof(struct cnfparamdescr),
+ cnfpdescr
+ };
+
+
+#if 0
+static void
+errfunc(__attribute__((unused)) void *usrptr, uchar *emsg)
+{
+ errmsg.LogError(0, RS_RET_CRYPROV_ERR, "Crypto Provider"
+ "Error: %s - disabling encryption", emsg);
+}
+#endif
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(lmcry_gcry)
+ dbgprintf("DDDD: lmcry_gcry: called construct\n");
+ pThis->ctx = gcryCtxNew();
+ENDobjConstruct(lmcry_gcry)
+
+
+/* destructor for the lmcry_gcry object */
+BEGINobjDestruct(lmcry_gcry) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(lmcry_gcry)
+ dbgprintf("DDDD: lmcry_gcry: called destruct\n");
+ rsgcryCtxDel(pThis->ctx);
+ENDobjDestruct(lmcry_gcry)
+
+
+/* apply all params from param block to us. This must be called
+ * after construction, but before the OnFileOpen() entry point.
+ * Defaults are expected to have been set during construction.
+ */
+rsRetVal
+SetCnfParam(void *pT, struct nvlst *lst)
+{
+ lmcry_gcry_t *pThis = (lmcry_gcry_t*) pT;
+ int i;
+ uchar *cstr;
+ struct cnfparamvals *pvals;
+ pvals = nvlstGetParams(lst, &pblk, NULL);
+ if(Debug) {
+ dbgprintf("param blk in lmcry_gcry:\n");
+ cnfparamsPrint(&pblk, pvals);
+ }
+
+ for(i = 0 ; i < pblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+#if 0
+ if(!strcmp(pblk.descr[i].name, "sig.hashfunction")) {
+ cstr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(gcrySetHashFunction(pThis->ctx, (char*)cstr) != 0) {
+ errmsg.LogError(0, RS_RET_ERR, "Hash function "
+ "'%s' unknown - using default", cstr);
+ }
+ free(cstr);
+ } else if(!strcmp(pblk.descr[i].name, "sig.timestampservice")) {
+ cstr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ gcrySetTimestamper(pThis->ctx, (char*) cstr);
+ free(cstr);
+ } else if(!strcmp(pblk.descr[i].name, "sig.block.sizelimit")) {
+ gcrySetBlockSizeLimit(pThis->ctx, pvals[i].val.d.n);
+ } else if(!strcmp(pblk.descr[i].name, "sig.keeprecordhashes")) {
+ gcrySetKeepRecordHashes(pThis->ctx, pvals[i].val.d.n);
+ } else if(!strcmp(pblk.descr[i].name, "sig.keeptreehashes")) {
+ gcrySetKeepTreeHashes(pThis->ctx, pvals[i].val.d.n);
+ } else {
+ DBGPRINTF("lmcry_gcry: program error, non-handled "
+ "param '%s'\n", pblk.descr[i].name);
+ }
+#endif
+ }
+ cnfparamvalsDestruct(pvals, &pblk);
+ return RS_RET_OK;
+}
+
+
+static rsRetVal
+OnFileOpen(void *pT, uchar *fn, void *pGF)
+{
+ lmcry_gcry_t *pThis = (lmcry_gcry_t*) pT;
+ gcryfile *pgf = (gcryfile*) pGF;
+ DEFiRet;
+dbgprintf("DDDD: cry: onFileOpen: %s\n", fn);
+ /* note: if *pgf is set to NULL, this auto-disables GT functions */
+ //*pgf = gcryCtxOpenFile(pThis->ctx, fn);
+
+ CHKiRet(rsgcryInitCrypt(pThis->ctx, pgf, GCRY_CIPHER_MODE_CBC, "TODO: init value"));
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+Encrypt(void *pF, uchar *rec, size_t *lenRec)
+{
+ DEFiRet;
+dbgprintf("DDDD: Encrypt (%u): %s\n", *lenRec-1, rec);
+ iRet = rsgcryEncrypt(pF, rec, lenRec);
+
+ RETiRet;
+}
+
+static rsRetVal
+OnFileClose(void *pF)
+{
+ DEFiRet;
+dbgprintf("DDDD: onFileClose\n");
+ gcryfileDestruct(pF);
+
+ RETiRet;
+}
+
+BEGINobjQueryInterface(lmcry_gcry)
+CODESTARTobjQueryInterface(lmcry_gcry)
+ if(pIf->ifVersion != cryprovCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+ pIf->Construct = (rsRetVal(*)(void*)) lmcry_gcryConstruct;
+ pIf->SetCnfParam = SetCnfParam;
+ pIf->Destruct = (rsRetVal(*)(void*)) lmcry_gcryDestruct;
+ pIf->OnFileOpen = OnFileOpen;
+ pIf->Encrypt = Encrypt;
+ pIf->OnFileClose = OnFileClose;
+finalize_it:
+ENDobjQueryInterface(lmcry_gcry)
+
+
+BEGINObjClassExit(lmcry_gcry, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(lmcry_gcry)
+ /* release objects we no longer need */
+ objRelease(errmsg, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+
+ rsgcryExit();
+ENDObjClassExit(lmcry_gcry)
+
+
+BEGINObjClassInit(lmcry_gcry, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+
+ if(rsgcryInit() != 0) {
+ errmsg.LogError(0, RS_RET_CRYPROV_ERR, "error initializing "
+ "crypto provider - cannot encrypt");
+ ABORT_FINALIZE(RS_RET_CRYPROV_ERR);
+ }
+ENDObjClassInit(lmcry_gcry)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ lmcry_gcryClassExit();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(lmcry_gcryClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ENDmodInit
diff --git a/runtime/lmcry_gcry.h b/runtime/lmcry_gcry.h
new file mode 100644
index 00000000..c0205ab9
--- /dev/null
+++ b/runtime/lmcry_gcry.h
@@ -0,0 +1,39 @@
+/* An implementation of the cryprov interface for libgcrypt.
+ *
+ * Copyright 2013 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_LMCRY_GCRY_H
+#define INCLUDED_LMCRY_GCRY_H
+#include "cryprov.h"
+
+/* interface is defined in cryprov.h, we just implement it! */
+#define lmcry_gcryCURR_IF_VERSION cryprovCURR_IF_VERSION
+typedef cryprov_if_t lmcry_gcry_if_t;
+
+/* the lmcry_gcry object */
+struct lmcry_gcry_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ gcryctx ctx;
+};
+typedef struct lmcry_gcry_s lmcry_gcry_t;
+
+/* prototypes */
+PROTOTYPEObj(lmcry_gcry);
+
+#endif /* #ifndef INCLUDED_LMCRY_GCRY_H */
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 5ba6ede7..cbc0401b 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -403,6 +403,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_INVLD_ANON_BITS = -2312,/**< mmanon: invalid number of bits to anonymize specified */
RS_RET_REPLCHAR_IGNORED = -2313,/**< mmanon: replacementChar parameter is ignored */
RS_RET_SIGPROV_ERR = -2320,/**< error in signature provider */
+ RS_RET_CRYPROV_ERR = -2321,/**< error in cryptography encryption provider */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
diff --git a/runtime/stream.c b/runtime/stream.c
index 00afcdaa..941fc39d 100644
--- a/runtime/stream.c
+++ b/runtime/stream.c
@@ -16,7 +16,7 @@
* it turns out to be problematic. Then, we need to quasi-refcount the number of accesses
* to the object.
*
- * Copyright 2008-2012 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2008-2013 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -56,6 +56,7 @@
#include "stream.h"
#include "unicode-helper.h"
#include "module-template.h"
+#include "cryprov.h"
#if HAVE_SYS_PRCTL_H
# include <sys/prctl.h>
#endif
@@ -253,6 +254,12 @@ doPhysOpen(strm_t *pThis)
pThis->bIsTTY = 0;
}
+dbgprintf("DDDD: cryprov %p\n", pThis->cryprov);
+ if(pThis->cryprov != NULL) {
+ iRet = pThis->cryprov->OnFileOpen(pThis->cryprovData,
+ pThis->pszCurrFName, &pThis->cryprovFileData);
+dbgprintf("DDDD: iREt cryprov->onFileOpen: %d\n", iRet);
+ }
finalize_it:
RETiRet;
}
@@ -405,6 +412,10 @@ static rsRetVal strmCloseFile(strm_t *pThis)
close(pThis->fd);
pThis->fd = -1;
pThis->inode = 0;
+ if(pThis->cryprov != NULL) {
+ pThis->cryprov->OnFileClose(pThis->cryprovFileData);
+ pThis->cryprovFileData = NULL;
+ }
}
if(pThis->fdDir != -1) {
@@ -1200,10 +1211,18 @@ strmPhysWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf)
DEFiRet;
ISOBJ_TYPE_assert(pThis, strm);
- DBGPRINTF("strmPhysWrite, stream %p, len %d\n", pThis, (int) lenBuf);
+ DBGPRINTF("strmPhysWrite, stream %p, len %u\n", pThis, (unsigned)lenBuf);
if(pThis->fd == -1)
CHKiRet(strmOpenFile(pThis));
+ /* here we place our crypto interface */
+dbgprintf("DDDD: doing crypto, len %d\n", lenBuf);
+ if(pThis->cryprov != NULL) {
+ pThis->cryprov->Encrypt(pThis->cryprovFileData, pBuf, &lenBuf);
+ }
+dbgprintf("DDDD: done crypto, len %d\n", lenBuf);
+ /* end crypto */
+
iWritten = lenBuf;
CHKiRet(doWriteCall(pThis, pBuf, &iWritten));
@@ -1600,6 +1619,8 @@ DEFpropSetMeth(strm, sIOBufSize, size_t)
DEFpropSetMeth(strm, iSizeLimit, off_t)
DEFpropSetMeth(strm, iFlushInterval, int)
DEFpropSetMeth(strm, pszSizeLimitCmd, uchar*)
+DEFpropSetMeth(strm, cryprov, cryprov_if_t*)
+DEFpropSetMeth(strm, cryprovData, void*)
static rsRetVal strmSetiMaxFiles(strm_t *pThis, int iNewVal)
{
@@ -1935,6 +1956,8 @@ CODESTARTobjQueryInterface(strm)
pIf->SetiSizeLimit = strmSetiSizeLimit;
pIf->SetiFlushInterval = strmSetiFlushInterval;
pIf->SetpszSizeLimitCmd = strmSetpszSizeLimitCmd;
+ pIf->Setcryprov = strmSetcryprov;
+ pIf->SetcryprovData = strmSetcryprovData;
finalize_it:
ENDobjQueryInterface(strm)
diff --git a/runtime/stream.h b/runtime/stream.h
index b7cc6d36..61d5ede2 100644
--- a/runtime/stream.h
+++ b/runtime/stream.h
@@ -41,7 +41,7 @@
* deflateInit2(zstrmptr, 6, Z_DEFLATED, 31, 9, Z_DEFAULT_STRATEGY);
* --------------------------------------------------------------------------
*
- * Copyright 2008, 2009 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2008-2013 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -70,6 +70,7 @@
#include "glbl.h"
#include "stream.h"
#include "zlibw.h"
+#include "cryprov.h"
/* stream types */
typedef enum {
@@ -134,6 +135,9 @@ typedef struct strm_s {
pthread_cond_t isEmpty;
unsigned short iEnq; /* this MUST be unsigned as we use module arithmetic (else invalid indexing happens!) */
unsigned short iDeq; /* this MUST be unsigned as we use module arithmetic (else invalid indexing happens!) */
+ cryprov_if_t *cryprov; /* ptr to crypto provider; NULL = do not encrypt */
+ void *cryprovData; /* opaque data ptr for provider use */
+ void *cryprovFileData;/* opaque data ptr for file instance */
short iCnt; /* current nbr of elements in buffer */
z_stream zstrm; /* zip stream to use */
struct {
@@ -190,8 +194,11 @@ BEGINinterface(strm) /* name must also be changed in ENDinterface macro! */
INTERFACEpropSetMeth(strm, bVeryReliableZip, int);
/* v8 added 2013-03-21 */
rsRetVal (*CheckFileChange)(strm_t *pThis);
+ /* v9 added 2013-04-04 */
+ INTERFACEpropSetMeth(strm, cryprov, cryprov_if_t*);
+ INTERFACEpropSetMeth(strm, cryprovData, void*);
ENDinterface(strm)
-#define strmCURR_IF_VERSION 8 /* increment whenever you change the interface structure! */
+#define strmCURR_IF_VERSION 9 /* increment whenever you change the interface structure! */
static inline int
strmGetCurrFileNum(strm_t *pStrm) {
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 21a32868..be093957 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -41,7 +41,7 @@ rsyslogd_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
# otherwise dependencies are not properly calculated (resulting in a
# potentially incomplete build, a problem we had several times...)
rsyslogd_LDADD = ../grammar/libgrammar.la ../runtime/librsyslog.la $(ZLIB_LIBS) $(PTHREADS_LIBS) $(RSRT_LIBS) $(SOL_LIBS) $(LIBEE_LIBS) $(LIBLOGNORM_LIBS) $(LIBUUID_LIBS)
-rsyslogd_LDFLAGS = -export-dynamic
+rsyslogd_LDFLAGS = -export-dynamic `libgcrypt-config --libs`
EXTRA_DIST = $(man_MANS) \
rsgtutil.rst \
diff --git a/tools/omfile.c b/tools/omfile.c
index faf3c24f..dfd52d80 100644
--- a/tools/omfile.c
+++ b/tools/omfile.c
@@ -70,6 +70,7 @@
#include "atomic.h"
#include "statsobj.h"
#include "sigprov.h"
+#include "cryprov.h"
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
@@ -151,6 +152,12 @@ typedef struct _instanceData {
void *sigprovData; /* opaque data ptr for provider use */
void *sigprovFileData;/* opaque data ptr for file instance */
sbool useSigprov; /* quicker than checkig ptr (1 vs 8 bytes!) */
+ uchar *cryprovName; /* crypto provider */
+ uchar *cryprovNameFull;/* full internal crypto provider name */
+ void *cryprovData; /* opaque data ptr for provider use */
+ void *cryprovFileData;/* opaque data ptr for file instance */
+ cryprov_if_t cryprov; /* ptr to crypto provider interface */
+ sbool useCryprov; /* quicker than checkig ptr (1 vs 8 bytes!) */
int iCurrElt; /* currently active cache element (-1 = none) */
int iCurrCacheSize; /* currently cache size (1-based) */
int iDynaFileCacheSize; /* size of file handle cache */
@@ -237,6 +244,7 @@ static struct cnfparamdescr actpdescr[] = {
{ "file", eCmdHdlrString, 0 }, /* either "file" or ... */
{ "dynafile", eCmdHdlrString, 0 }, /* "dynafile" MUST be present */
{ "sig.provider", eCmdHdlrGetWord, 0 },
+ { "cry.provider", eCmdHdlrGetWord, 0 },
{ "template", eCmdHdlrGetWord, 0 }
};
static struct cnfparamblk actpblk =
@@ -589,6 +597,10 @@ prepareFile(instanceData *pData, uchar *newFileName)
CHKiRet(strm.SetbSync(pData->pStrm, pData->bSyncFile));
CHKiRet(strm.SetsType(pData->pStrm, STREAMTYPE_FILE_SINGLE));
CHKiRet(strm.SetiSizeLimit(pData->pStrm, pData->iSizeLimit));
+ if(pData->useCryprov) {
+ CHKiRet(strm.Setcryprov(pData->pStrm, &pData->cryprov));
+ CHKiRet(strm.SetcryprovData(pData->pStrm, pData->cryprovData));
+ }
/* set the flush interval only if we actually use it - otherwise it will activate
* async processing, which is a real performance waste if we do not do buffered
* writes! -- rgerhards, 2009-07-06
@@ -689,7 +701,7 @@ prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts)
* but it could be triggered in the common case of a failed open() system call.
* rgerhards, 2010-03-22
*/
- pData->pStrm = pData->sigprovFileData = NULL;
+ pData->pStrm = NULL, pData->sigprovFileData = NULL;
if(iFirstFree == -1 && (pData->iCurrCacheSize < pData->iDynaFileCacheSize)) {
/* there is space left, so set it to that index */
@@ -885,6 +897,13 @@ CODESTARTfreeInstance
free(pData->sigprovName);
free(pData->sigprovNameFull);
}
+ if(pData->useCryprov) {
+ pData->cryprov.Destruct(&pData->cryprovData);
+ obj.ReleaseObj(__FILE__, pData->cryprovNameFull+2, pData->cryprovNameFull,
+ (void*) &pData->cryprov);
+ free(pData->cryprovName);
+ free(pData->cryprovNameFull);
+ }
ENDfreeInstance
@@ -951,7 +970,9 @@ setInstParamDefaults(instanceData *pData)
pData->iFlushInterval = FLUSH_INTRVL_DFLT;
pData->bUseAsyncWriter = USE_ASYNCWRITER_DFLT;
pData->sigprovName = NULL;
+ pData->cryprovName = NULL;
pData->useSigprov = 0;
+ pData->useCryprov = 0;
}
@@ -1033,6 +1054,48 @@ initSigprov(instanceData *pData, struct nvlst *lst)
done: return;
}
+static inline void
+initCryprov(instanceData *pData, struct nvlst *lst)
+{
+ uchar szDrvrName[1024];
+
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmcry_%s", pData->cryprovName)
+ == sizeof(szDrvrName)) {
+ errmsg.LogError(0, RS_RET_ERR, "omfile: crypto provider "
+ "name is too long: '%s' - encryption disabled",
+ pData->cryprovName);
+ goto done;
+ }
+ pData->cryprovNameFull = ustrdup(szDrvrName);
+
+ pData->cryprov.ifVersion = cryprovCURR_IF_VERSION;
+ /* The pDrvrName+2 below is a hack to obtain the object name. It
+ * safes us to have yet another variable with the name without "lm" in
+ * front of it. If we change the module load interface, we may re-think
+ * about this hack, but for the time being it is efficient and clean enough.
+ */
+ if(obj.UseObj(__FILE__, szDrvrName, szDrvrName, (void*) &pData->cryprov)
+ != RS_RET_OK) {
+ errmsg.LogError(0, RS_RET_LOAD_ERROR, "omfile: could not load "
+ "crypto provider '%s' - encryption disabled",
+ szDrvrName);
+ goto done;
+ }
+
+ if(pData->cryprov.Construct(&pData->cryprovData) != RS_RET_OK) {
+ errmsg.LogError(0, RS_RET_SIGPROV_ERR, "omfile: error constructing "
+ "crypto provider %s dataset - encryption disabled",
+ szDrvrName);
+ goto done;
+ }
+ pData->cryprov.SetCnfParam(pData->cryprovData, lst);
+
+ dbgprintf("loaded crypto provider %s, data instance at %p\n",
+ szDrvrName, pData->cryprovData);
+ pData->useCryprov = 1;
+done: return;
+}
+
BEGINnewActInst
struct cnfparamvals *pvals;
uchar *tplToUse;
@@ -1102,6 +1165,8 @@ CODESTARTnewActInst
pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if(!strcmp(actpblk.descr[i].name, "sig.provider")) {
pData->sigprovName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "cry.provider")) {
+ pData->cryprovName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else {
dbgprintf("omfile: program error, non-handled "
"param '%s'\n", actpblk.descr[i].name);
@@ -1118,6 +1183,10 @@ CODESTARTnewActInst
initSigprov(pData, lst);
}
+ if(pData->cryprovName != NULL) {
+ initCryprov(pData, lst);
+ }
+
tplToUse = ustrdup((pData->tplName == NULL) ? getDfltTpl() : pData->tplName);
CHKiRet(OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_NO_RQD_TPL_OPTS));