summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/libgcry.c27
-rw-r--r--runtime/libgcry.h4
-rw-r--r--runtime/lmcry_gcry.c31
-rw-r--r--runtime/stream.c5
-rw-r--r--tools/Makefile.am17
-rw-r--r--tools/omfile.c18
-rw-r--r--tools/rscryutil.c236
-rw-r--r--tools/rscryutil.rst80
8 files changed, 386 insertions, 32 deletions
diff --git a/runtime/libgcry.c b/runtime/libgcry.c
index 8184c160..5f1dbf58 100644
--- a/runtime/libgcry.c
+++ b/runtime/libgcry.c
@@ -27,6 +27,7 @@
#include "rsyslog.h"
#include "libgcry.h"
+#define GCRY_CIPHER GCRY_CIPHER_3DES // TODO: make configurable
static inline gcryfile
gcryfileConstruct(gcryctx ctx)
@@ -98,20 +99,34 @@ removePadding(char *buf, size_t *plen)
done: return;
}
+/* returns 0 on succes, positive if key length does not match and key
+ * of return value size is required.
+ */
+int
+rsgcrySetKey(gcryctx ctx, unsigned char *key, uint16_t keyLen)
+{
+ uint16_t reqKeyLen = gcry_cipher_get_algo_keylen(GCRY_CIPHER);
+ int r;
+
+ if(keyLen != reqKeyLen)
+ r = reqKeyLen;
+ ctx->keyLen = keyLen;
+ ctx->key = malloc(keyLen);
+ memcpy(ctx->key, key, keyLen);
+ r = 0;
+done: return r;
+}
+
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;
+ 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 *
@@ -125,7 +140,7 @@ rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, int gcry_mode, char *iniVector)
ABORT_FINALIZE(RS_RET_ERR);
}
- gcryError = gcry_cipher_setkey(gf->chd, aesSymKey, keyLength);
+ gcryError = gcry_cipher_setkey(gf->chd, gf->ctx->key, gf->ctx->keyLen);
if (gcryError) {
dbgprintf("gcry_cipher_setkey failed: %s/%s\n",
gcry_strsource(gcryError),
diff --git a/runtime/libgcry.h b/runtime/libgcry.h
index 0405162f..608abd6c 100644
--- a/runtime/libgcry.h
+++ b/runtime/libgcry.h
@@ -24,7 +24,8 @@
struct gcryctx_s {
- void *usrptr; /* for error function */
+ uchar *key;
+ size_t keyLen;
};
typedef struct gcryctx_s *gcryctx;
typedef struct gcryfile_s *gcryfile;
@@ -38,6 +39,7 @@ struct gcryfile_s {
int rsgcryInit(void);
void rsgcryExit(void);
+int rsgcrySetKey(gcryctx ctx, unsigned char *key, uint16_t keyLen);
gcryctx gcryCtxNew(void);
void rsgcryCtxDel(gcryctx ctx);
int gcryfileDestruct(gcryfile gf);
diff --git a/runtime/lmcry_gcry.c b/runtime/lmcry_gcry.c
index 6800055d..ce0fef2f 100644
--- a/runtime/lmcry_gcry.c
+++ b/runtime/lmcry_gcry.c
@@ -44,6 +44,7 @@ DEFobjCurrIf(glbl)
/* tables for interfacing with the v6 config system */
static struct cnfparamdescr cnfpdescr[] = {
+ { "cry.key", eCmdHdlrGetWord, 0 },
{ "cry.mode", eCmdHdlrGetWord, 0 }, /* CBC, ECB, etc */
{ "cry.algo", eCmdHdlrGetWord, 0 }
};
@@ -83,12 +84,13 @@ ENDobjDestruct(lmcry_gcry)
* after construction, but before the OnFileOpen() entry point.
* Defaults are expected to have been set during construction.
*/
-rsRetVal
+static rsRetVal
SetCnfParam(void *pT, struct nvlst *lst)
{
lmcry_gcry_t *pThis = (lmcry_gcry_t*) pT;
- int i;
+ int i, r;
uchar *cstr;
+ uchar *key = NULL;
struct cnfparamvals *pvals;
pvals = nvlstGetParams(lst, &pblk, NULL);
if(Debug) {
@@ -99,14 +101,9 @@ SetCnfParam(void *pT, struct nvlst *lst)
for(i = 0 ; i < pblk.nParams ; ++i) {
if(!pvals[i].bUsed)
continue;
+ if(!strcmp(pblk.descr[i].name, "cry.key")) {
+ key = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
#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);
@@ -120,10 +117,24 @@ SetCnfParam(void *pT, struct nvlst *lst)
} else {
DBGPRINTF("lmcry_gcry: program error, non-handled "
"param '%s'\n", pblk.descr[i].name);
- }
#endif
+ }
}
+ if(key != NULL) {
+ errmsg.LogError(0, RS_RET_ERR, "Note: specifying an actual key directly from the "
+ "config file is highly insecure - DO NOT USE FOR PRODUCTION");
+ r = rsgcrySetKey(pThis->ctx, key, strlen((char*)key));
+ if(r > 0) {
+ errmsg.LogError(0, RS_RET_ERR, "Key length %d expected, but "
+ "key of length %d given", r, strlen((char*)key));
+ }
+ }
+
cnfparamvalsDestruct(pvals, &pblk);
+ if(key != NULL) {
+ memset(key, 0, strlen((char*)key));
+ free(key);
+ }
return RS_RET_OK;
}
diff --git a/runtime/stream.c b/runtime/stream.c
index 941fc39d..b31520b0 100644
--- a/runtime/stream.c
+++ b/runtime/stream.c
@@ -256,9 +256,8 @@ doPhysOpen(strm_t *pThis)
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);
+ CHKiRet(pThis->cryprov->OnFileOpen(pThis->cryprovData,
+ pThis->pszCurrFName, &pThis->cryprovFileData));
}
finalize_it:
RETiRet;
diff --git a/tools/Makefile.am b/tools/Makefile.am
index be093957..8957d713 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -42,6 +42,7 @@ rsyslogd_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
# 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 `libgcrypt-config --libs`
+#rsyslogd_LDFLAGS = -export-dynamic $(LIBGCRYPT_LIBS)
EXTRA_DIST = $(man_MANS) \
rsgtutil.rst \
@@ -64,10 +65,6 @@ logctl_LDADD = $(LIBMONGO_CLIENT_LIBS)
endif
if ENABLE_GUARDTIME
bin_PROGRAMS += rsgtutil
-#bin_PROGRAMS += logsigner rsgtutil
-#logsigner = logsigner.c
-#logsigner_CPPFLAGS = $(RSRT_CFLAGS) $(GUARDTIME_CFLAGS)
-#logsigner_LDADD = ../runtime/librsgt.la $(GUARDTIME_LIBS)
rsgtutil = rsgtutil.c
rsgtutil_CPPFLAGS = $(RSRT_CFLAGS) $(GUARDTIME_CFLAGS)
rsgtutil_LDADD = ../runtime/librsgt.la $(GUARDTIME_LIBS)
@@ -77,4 +74,16 @@ man1_MANS = rsgtutil.1
CLEANFILES = rsgtutil.1
EXTRA_DIST+= rsgtutil.1
endif
+if ENABLE_LIBGCRYPT
+bin_PROGRAMS += rscryutil
+rscryutil = rscryutil.c
+rscryutil_CPPFLAGS = $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS)
+rscryutil_LDFLAGS = `libgcrypt-config --libs`
+#rscryutil_LDFLAGS = $(LIBGCRYPT_LIBS)
+rscryutil.1: rscryutil.rst
+ $(AM_V_GEN) $(RST2MAN) $< $@
+man1_MANS = rscryutil.1
+CLEANFILES = rscryutil.1
+EXTRA_DIST+= rscryutil.1
+endif
endif
diff --git a/tools/omfile.c b/tools/omfile.c
index dfd52d80..46d882bf 100644
--- a/tools/omfile.c
+++ b/tools/omfile.c
@@ -1054,17 +1054,18 @@ initSigprov(instanceData *pData, struct nvlst *lst)
done: return;
}
-static inline void
+static inline rsRetVal
initCryprov(instanceData *pData, struct nvlst *lst)
{
uchar szDrvrName[1024];
+ DEFiRet;
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;
+ ABORT_FINALIZE(RS_RET_ERR);
}
pData->cryprovNameFull = ustrdup(szDrvrName);
@@ -1079,21 +1080,22 @@ initCryprov(instanceData *pData, struct nvlst *lst)
errmsg.LogError(0, RS_RET_LOAD_ERROR, "omfile: could not load "
"crypto provider '%s' - encryption disabled",
szDrvrName);
- goto done;
+ ABORT_FINALIZE(RS_RET_CRYPROV_ERR);
}
if(pData->cryprov.Construct(&pData->cryprovData) != RS_RET_OK) {
- errmsg.LogError(0, RS_RET_SIGPROV_ERR, "omfile: error constructing "
+ errmsg.LogError(0, RS_RET_CRYPROV_ERR, "omfile: error constructing "
"crypto provider %s dataset - encryption disabled",
szDrvrName);
- goto done;
+ ABORT_FINALIZE(RS_RET_CRYPROV_ERR);
}
- pData->cryprov.SetCnfParam(pData->cryprovData, lst);
+ CHKiRet(pData->cryprov.SetCnfParam(pData->cryprovData, lst));
dbgprintf("loaded crypto provider %s, data instance at %p\n",
szDrvrName, pData->cryprovData);
pData->useCryprov = 1;
-done: return;
+finalize_it:
+ RETiRet;
}
BEGINnewActInst
@@ -1184,7 +1186,7 @@ CODESTARTnewActInst
}
if(pData->cryprovName != NULL) {
- initCryprov(pData, lst);
+ CHKiRet(initCryprov(pData, lst));
}
tplToUse = ustrdup((pData->tplName == NULL) ? getDfltTpl() : pData->tplName);
diff --git a/tools/rscryutil.c b/tools/rscryutil.c
new file mode 100644
index 00000000..755371f2
--- /dev/null
+++ b/tools/rscryutil.c
@@ -0,0 +1,236 @@
+/* This is a tool for dumpoing the content of GuardTime TLV
+ * files in a (somewhat) human-readable manner.
+ *
+ * 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 exprs or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <gcrypt.h>
+
+
+static enum { MD_DECRYPT
+} mode = MD_DECRYPT;
+static int verbose = 0;
+static gcry_cipher_hd_t gcry_chd;
+static size_t blkLength;
+
+static int
+initCrypt(int gcry_mode, char *iv, char *key)
+{
+ #define GCRY_CIPHER GCRY_CIPHER_3DES // TODO: make configurable
+ int r = 0;
+ gcry_error_t gcryError;
+
+ blkLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER);
+ size_t keyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER);
+ if(strlen(key) != keyLength) {
+ fprintf(stderr, "invalid key lengtjh; key is %u characters, but "
+ "exactly %u characters are required\n", strlen(key),
+ keyLength);
+ r = 1; goto done;
+ }
+
+ gcryError = gcry_cipher_open(&gcry_chd, GCRY_CIPHER, gcry_mode, 0);
+ if (gcryError) {
+ printf("gcry_cipher_open failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ r = 1; goto done;
+ }
+
+ gcryError = gcry_cipher_setkey(gcry_chd, key, keyLength);
+ if (gcryError) {
+ printf("gcry_cipher_setkey failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ r = 1; goto done;
+ }
+
+ gcryError = gcry_cipher_setiv(gcry_chd, iv, blkLength);
+ if (gcryError) {
+ printf("gcry_cipher_setiv failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ r = 1; goto done;
+ }
+done: return r;
+}
+
+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;
+}
+
+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(
+ gcry_chd, // 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;
+ }
+ removePadding(buf, &nRead);
+ nWritten = fwrite(buf, 1, nRead, fpout);
+ if(nWritten != nRead) {
+ perror("fpout");
+ return;
+ }
+ }
+}
+
+
+static void
+decrypt(char *name, char *key)
+{
+ FILE *logfp = NULL;
+ //, *sigfp = NULL;
+ int r = 0;
+ //char sigfname[4096];
+
+ if(!strcmp(name, "-")) {
+ fprintf(stderr, "decrypt mode cannot work on stdin\n");
+ goto err;
+ } else {
+ if((logfp = fopen(name, "r")) == NULL) {
+ perror(name);
+ goto err;
+ }
+#if 0
+ snprintf(sigfname, sizeof(sigfname), "%s.gtsig", name);
+ sigfname[sizeof(sigfname)-1] = '\0';
+ if((sigfp = fopen(sigfname, "r")) == NULL) {
+ perror(sigfname);
+ goto err;
+ }
+#endif
+ }
+
+ if(initCrypt(GCRY_CIPHER_MODE_CBC, "TODO: init value", key) != 0)
+ goto err;
+ doDeCrypt(logfp, stdout);
+ gcry_cipher_close(gcry_chd);
+ fclose(logfp); logfp = NULL;
+ return;
+
+err:
+ fprintf(stderr, "error %d processing file %s\n", r, name);
+ if(logfp != NULL)
+ fclose(logfp);
+}
+
+
+static struct option long_options[] =
+{
+ {"verbose", no_argument, NULL, 'v'},
+ {"version", no_argument, NULL, 'V'},
+ {"decrypt", no_argument, NULL, 'd'},
+ {"key", required_argument, NULL, 'k'},
+ {NULL, 0, NULL, 0}
+};
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+ int opt;
+ char *key = "";
+
+ while(1) {
+ opt = getopt_long(argc, argv, "dk:vV", long_options, NULL);
+ if(opt == -1)
+ break;
+ switch(opt) {
+ case 'd':
+ mode = MD_DECRYPT;
+ break;
+ case 'k':
+ fprintf(stderr, "WARNING: specifying the actual key "
+ "via the command line is highly insecure\n"
+ "Do NOT use this for PRODUCTION use.\n");
+ key = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'V':
+ fprintf(stderr, "rsgtutil " VERSION "\n");
+ exit(0);
+ break;
+ case '?':
+ break;
+ default:fprintf(stderr, "getopt_long() returns unknown value %d\n", opt);
+ return 1;
+ }
+ }
+
+ if(optind == argc)
+ decrypt("-", key);
+ else {
+ for(i = optind ; i < argc ; ++i)
+ decrypt(argv[i], key); /* currently only mode ;) */
+ }
+
+ memset(key, 0, strlen(key)); /* zero-out key store */
+ return 0;
+}
+ //char *aesSymKey = "123456789012345678901234"; // TODO: TEST ONLY
diff --git a/tools/rscryutil.rst b/tools/rscryutil.rst
new file mode 100644
index 00000000..7e3ab5b4
--- /dev/null
+++ b/tools/rscryutil.rst
@@ -0,0 +1,80 @@
+=========
+rscryutil
+=========
+
+--------------------------
+Manage Encrypted Log Files
+--------------------------
+
+:Author: Rainer Gerhards <rgerhards@adiscon.com>
+:Date: 2013-04-08
+:Manual section: 1
+
+SYNOPSIS
+========
+
+::
+
+ rscryutil [OPTIONS] [FILE] ...
+
+
+DESCRIPTION
+===========
+
+This tool performs various operations on encrypted log files.
+Most importantly, it provides the ability to decrypt them.
+
+
+OPTIONS
+=======
+
+-d, --decrypt
+ Select decryption mode. This is the default mode.
+
+-v, --verbose
+ Select verbose mode.
+
+-k, --key <KEY>
+ TESTING AID, NOT FOR PRODUCTION USE. This uses the KEY specified
+ on the command line. This is the actual key, and as such this mode
+ is highly insecure. However, it can be useful for intial testing
+ steps. This option may be removed in the future.
+
+
+OPERATION MODES
+===============
+
+The operation mode specifies what exactly the tool does with the provided
+files. The default operation mode is "dump", but this may change in the future.
+Thus, it is recommended to always set the operations mode explicitely. If
+multiple operations mode are set on the command line, results are
+unpredictable.
+
+decrypt
+-------
+
+The provided log files are decrypted.
+
+EXIT CODES
+==========
+
+The command returns an exit code of 0 if everything went fine, and some
+other code in case of failures.
+
+
+EXAMPLES
+========
+
+**rscryutil logfile**
+
+Decrypts "logfile" and sends data to stdout.
+
+SEE ALSO
+========
+**rsyslogd(8)**
+
+COPYRIGHT
+=========
+
+This page is part of the *rsyslog* project, and is available under
+LGPLv2.