summaryrefslogtreecommitdiffstats
path: root/runtime/lmsig_ksi-ls12.c
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lmsig_ksi-ls12.c')
-rw-r--r--runtime/lmsig_ksi-ls12.c346
1 files changed, 346 insertions, 0 deletions
diff --git a/runtime/lmsig_ksi-ls12.c b/runtime/lmsig_ksi-ls12.c
new file mode 100644
index 0000000..0336bc2
--- /dev/null
+++ b/runtime/lmsig_ksi-ls12.c
@@ -0,0 +1,346 @@
+/* lmsig_ksi-ls12.c
+ *
+ * An implementation of the sigprov interface for KSI-LS12.
+ *
+ * Copyright 2013-2017 Adiscon GmbH and Guardtime, Inc.
+ *
+ * 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 "sigprov.h"
+#include "lmsig_ksi-ls12.h"
+
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+
+/* tables for interfacing with the v6 config system */
+static struct cnfparamdescr cnfpdescr[] = {
+ { "sig.hashfunction", eCmdHdlrGetWord, 0 },
+ { "sig.aggregator.url", eCmdHdlrGetWord, CNFPARAM_REQUIRED},
+ { "sig.aggregator.user", eCmdHdlrGetWord, 0},
+ { "sig.aggregator.key", eCmdHdlrGetWord, 0},
+ { "sig.aggregator.hmacAlg", eCmdHdlrGetWord, 0 },
+ { "sig.block.levelLimit", eCmdHdlrSize, CNFPARAM_REQUIRED},
+ { "sig.block.timeLimit", eCmdHdlrInt, 0},
+ { "sig.block.signtimeout", eCmdHdlrInt, 0},
+ { "sig.confinterval", eCmdHdlrInt, 0},
+ { "sig.keeprecordhashes", eCmdHdlrBinary, 0 },
+ { "sig.keeptreehashes", eCmdHdlrBinary, 0},
+ { "sig.fileformat", eCmdHdlrString, 0},
+ { "sig.syncmode", eCmdHdlrString, 0},
+ { "sig.randomsource", eCmdHdlrString, 0},
+ { "sig.debugfile", eCmdHdlrString, 0},
+ { "sig.debuglevel", eCmdHdlrInt, 0},
+ { "dirowner", eCmdHdlrUID, 0}, /* legacy: dirowner */
+ { "dirownernum", eCmdHdlrInt, 0 }, /* legacy: dirownernum */
+ { "dirgroup", eCmdHdlrGID, 0 }, /* legacy: dirgroup */
+ { "dirgroupnum", eCmdHdlrInt, 0 }, /* legacy: dirgroupnum */
+ { "fileowner", eCmdHdlrUID, 0 }, /* legacy: fileowner */
+ { "fileownernum", eCmdHdlrInt, 0 }, /* legacy: fileownernum */
+ { "filegroup", eCmdHdlrGID, 0 }, /* legacy: filegroup */
+ { "filegroupnum", eCmdHdlrInt, 0 }, /* legacy: filegroupnum */
+ { "dircreatemode", eCmdHdlrFileCreateMode, 0 }, /* legacy: dircreatemode */
+ { "filecreatemode", eCmdHdlrFileCreateMode, 0 } /* legacy: filecreatemode */
+};
+static struct cnfparamblk pblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(cnfpdescr)/sizeof(struct cnfparamdescr),
+ cnfpdescr
+ };
+
+
+static void
+errfunc(__attribute__((unused)) void *usrptr, uchar *emsg)
+{
+ LogError(0, RS_RET_SIGPROV_ERR, "KSI Signature Provider"
+ "Error: %s", emsg);
+}
+
+static void
+logfunc(__attribute__((unused)) void *usrptr, uchar *emsg)
+{
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO,
+ "KSI/LS12 Signature Provider: %s", emsg);
+}
+
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(lmsig_ksi_ls12)
+ pThis->ctx = rsksiCtxNew();
+ rsksisetErrFunc(pThis->ctx, errfunc, NULL);
+ rsksisetLogFunc(pThis->ctx, logfunc, NULL);
+ENDobjConstruct(lmsig_ksi_ls12)
+
+
+/* destructor for the lmsig_ksi object */
+BEGINobjDestruct(lmsig_ksi_ls12) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(lmsig_ksi_ls12)
+ rsksiCtxDel(pThis->ctx);
+ENDobjDestruct(lmsig_ksi_ls12)
+
+#define REPORT_PARAM_MISSING(param) \
+ do { \
+ pThis->ctx->disabled = true; \
+ LogError(0, RS_RET_ERR, "%s missing - signing disabled", param); \
+ /* TODO: ABORT_FINALIZE actually is useless because the return value is not checked by the caller*/ \
+ ABORT_FINALIZE(RS_RET_KSI_ERR); \
+ } while(0)
+
+
+
+/* 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.
+ */
+static rsRetVal
+SetCnfParam(void *pT, struct nvlst *lst)
+{
+ char *ag_uri = NULL, *ag_loginid = NULL, *ag_key = NULL;
+ char *hash=NULL, *hmac = NULL;
+ lmsig_ksi_ls12_t *pThis = (lmsig_ksi_ls12_t*) pT;
+ int i;
+ uchar *cstr;
+ struct cnfparamvals *pvals;
+ DEFiRet;
+ pvals = nvlstGetParams(lst, &pblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_ERR, "Failed to load configuration - signing disabled");
+ pThis->ctx->disabled=true;
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ if(Debug) {
+ dbgprintf("sig param blk in lmsig_ksi:\n");
+ cnfparamsPrint(&pblk, pvals);
+ }
+
+ for(i = 0 ; i < pblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(pblk.descr[i].name, "sig.hashfunction")) {
+ hash = (char*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(pblk.descr[i].name, "sig.aggregator.url")) {
+ ag_uri = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "sig.aggregator.user")) {
+ ag_loginid = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(pblk.descr[i].name, "sig.aggregator.key")) {
+ ag_key = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "sig.aggregator.hmacAlg")) {
+ hmac = (char*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(pblk.descr[i].name, "sig.block.levelLimit")) {
+ if (pvals[i].val.d.n < 2) {
+ LogError(0, RS_RET_ERR, "sig.block.levelLimit "
+ "%llu invalid - signing disabled", pvals[i].val.d.n);
+ pThis->ctx->disabled = true;
+ } else {
+ rsksiSetBlockLevelLimit(pThis->ctx, pvals[i].val.d.n);
+ }
+ } else if (!strcmp(pblk.descr[i].name, "sig.block.timeLimit")) {
+ if (pvals[i].val.d.n < 0) {
+ LogError(0, RS_RET_ERR, "sig.block.timeLimit "
+ "%llu invalid - signing disabled", pvals[i].val.d.n);
+ pThis->ctx->disabled = true;
+ } else {
+ rsksiSetBlockTimeLimit(pThis->ctx, pvals[i].val.d.n);
+ }
+ } else if (!strcmp(pblk.descr[i].name, "sig.confinterval")) {
+ if (pvals[i].val.d.n < 0) {
+ LogError(0, RS_RET_ERR, "sig.confinterval "
+ "%llu invalid - signing disabled", pvals[i].val.d.n);
+ pThis->ctx->disabled = true;
+ } else {
+ rsksiSetConfInterval(pThis->ctx, pvals[i].val.d.n);
+ }
+ } else if (!strcmp(pblk.descr[i].name, "sig.keeprecordhashes")) {
+ rsksiSetKeepRecordHashes(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "sig.block.signtimeout")) {
+ if (pvals[i].val.d.n < 0) {
+ LogError(0, RS_RET_ERR, "sig.block.signtimeout "
+ "%llu invalid - signing disabled", pvals[i].val.d.n);
+ pThis->ctx->disabled = true;
+ } else {
+ rsksiSetBlockSigTimeout(pThis->ctx, pvals[i].val.d.n);
+ }
+ } else if(!strcmp(pblk.descr[i].name, "sig.keeptreehashes")) {
+ rsksiSetKeepTreeHashes(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "sig.syncmode")) {
+ cstr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ if (!strcasecmp((char*) cstr, "sync")) rsksiSetSyncMode(pThis->ctx, LOGSIG_SYNCHRONOUS);
+ else if (!strcasecmp((char*) cstr, "async")) rsksiSetSyncMode(pThis->ctx, LOGSIG_ASYNCHRONOUS);
+ else LogError(0, RS_RET_ERR, "sig.syncmode '%s' unknown - using default", cstr);
+ free(cstr);
+ } else if (!strcmp(pblk.descr[i].name, "sig.randomsource")) {
+ cstr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ rsksiSetRandomSource(pThis->ctx, (char*) cstr);
+ free(cstr);
+ } else if (!strcmp(pblk.descr[i].name, "sig.debugfile")) {
+ cstr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ rsksiSetDebugFile(pThis->ctx, (char*) cstr);
+ free(cstr);
+ } else if (!strcmp(pblk.descr[i].name, "sig.debuglevel")) {
+ rsksiSetDebugLevel(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "dirowner")) {
+ rsksiSetDirUID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "dirownernum")) {
+ rsksiSetDirUID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "dirgroup")) {
+ rsksiSetDirGID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "dirgroupnum")) {
+ rsksiSetDirGID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "fileowner")) {
+ rsksiSetFileUID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "fileownernum")) {
+ rsksiSetFileUID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "filegroup")) {
+ rsksiSetFileGID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "filegroupnum")) {
+ rsksiSetFileGID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "dircreatemode")) {
+ rsksiSetDirCreateMode(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "filecreatemode")) {
+ rsksiSetCreateMode(pThis->ctx, pvals[i].val.d.n);
+ } else {
+ DBGPRINTF("lmsig_ksi: program error, non-handled "
+ "param '%s'\n", pblk.descr[i].name);
+ }
+ }
+
+ if(rsksiSetHashFunction(pThis->ctx, hash ? hash : (char*) "default") != KSI_OK) {
+ ABORT_FINALIZE(RS_RET_KSI_ERR);
+ }
+
+ if(rsksiSetHmacFunction(pThis->ctx, hmac ? hmac : (char*) "default") != KSI_OK) {
+ ABORT_FINALIZE(RS_RET_KSI_ERR);
+ }
+
+ if(rsksiSetAggregator(pThis->ctx, ag_uri, ag_loginid, ag_key) != KSI_OK) {
+ ABORT_FINALIZE(RS_RET_KSI_ERR);
+ }
+
+finalize_it:
+ free(ag_uri);
+ free(ag_loginid);
+ free(ag_key);
+ free(hash);
+ free(hmac);
+
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &pblk);
+ RETiRet;
+}
+
+
+static rsRetVal
+OnFileOpen(void *pT, uchar *fn, void *pGF) {
+ lmsig_ksi_ls12_t *pThis = (lmsig_ksi_ls12_t*) pT;
+ ksifile *pgf = (ksifile*) pGF;
+ DEFiRet;
+ /* note: if *pgf is set to NULL, this auto-disables GT functions */
+ *pgf = rsksiCtxOpenFile(pThis->ctx, fn);
+ sigblkInitKSI(*pgf);
+ RETiRet;
+}
+
+/* Note: we assume that the record is terminated by a \n.
+ * As of the GuardTime paper, \n is not part of the signed
+ * message, so we subtract one from the record size. This
+ * may cause issues with non-standard formats, but let's
+ * see how things evolve (the verifier will not work in
+ * any case when the records are not \n delimited...).
+ * rgerhards, 2013-03-17
+ */
+static rsRetVal
+OnRecordWrite(void *pF, uchar *rec, rs_size_t lenRec)
+{
+ DEFiRet;
+ DBGPRINTF("lmsig_ksi-ls12: onRecordWrite (%d): %s\n", lenRec - 1, rec);
+ sigblkAddRecordKSI(pF, rec, lenRec - 1);
+
+ RETiRet;
+}
+
+static rsRetVal
+OnFileClose(void *pF)
+{
+ DEFiRet;
+ DBGPRINTF("lmsig_ksi_ls12: onFileClose\n");
+ rsksifileDestruct(pF);
+
+ RETiRet;
+}
+
+BEGINobjQueryInterface(lmsig_ksi_ls12)
+CODESTARTobjQueryInterface(lmsig_ksi_ls12)
+ if (pIf->ifVersion != sigprovCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+ pIf->Construct = (rsRetVal(*)(void*)) lmsig_ksi_ls12Construct;
+ pIf->SetCnfParam = SetCnfParam;
+ pIf->Destruct = (rsRetVal(*)(void*)) lmsig_ksi_ls12Destruct;
+ pIf->OnFileOpen = OnFileOpen;
+ pIf->OnRecordWrite = OnRecordWrite;
+ pIf->OnFileClose = OnFileClose;
+finalize_it:
+ENDobjQueryInterface(lmsig_ksi_ls12)
+
+
+BEGINObjClassExit(lmsig_ksi_ls12, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(lmsig_ksi_ls12)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ENDObjClassExit(lmsig_ksi_ls12)
+
+
+BEGINObjClassInit(lmsig_ksi_ls12, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ENDObjClassInit(lmsig_ksi_ls12)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+lmsig_ksi_ls12ClassExit();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CHKiRet(lmsig_ksi_ls12ClassInit(pModInfo));
+ENDmodInit