diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2013-04-05 12:08:49 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2013-04-05 12:08:49 +0200 |
commit | 0cee769fcdc9716ccb2a60b6473062a60f640bb3 (patch) | |
tree | 72205eed0e6d570bda683cdbbc37d17a0f3a21aa | |
parent | 0f87c631e7eac2ccbd36cd875d64de29dd7c714c (diff) | |
download | rsyslog-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.ac | 2 | ||||
-rw-r--r-- | runtime/Makefile.am | 22 | ||||
-rw-r--r-- | runtime/cryprov.h | 41 | ||||
-rw-r--r-- | runtime/libgcry.c | 224 | ||||
-rw-r--r-- | runtime/libgcry.h | 47 | ||||
-rw-r--r-- | runtime/lmcry_gcry.c | 224 | ||||
-rw-r--r-- | runtime/lmcry_gcry.h | 39 | ||||
-rw-r--r-- | runtime/rsyslog.h | 1 | ||||
-rw-r--r-- | runtime/stream.c | 27 | ||||
-rw-r--r-- | runtime/stream.h | 11 | ||||
-rw-r--r-- | tools/Makefile.am | 2 | ||||
-rw-r--r-- | tools/omfile.c | 71 |
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)); |