mirror of
https://github.com/rsyslog/rsyslog.git
synced 2025-12-16 20:20:41 +01:00
This commit applies the new canonical formatting style using `clang-format` with custom settings (notably 4-space indentation), as part of our shift toward automated formatting normalization. ⚠️ No functional changes are included — only whitespace and layout modifications as produced by `clang-format`. This change is part of the formatting modernization strategy discussed in: https://github.com/rsyslog/rsyslog/issues/5747 Key context: - Formatting is now treated as a disposable view, normalized via tooling. - The `.clang-format` file defines the canonical style. - A fixup script (`devtools/format-code.sh`) handles remaining edge cases. - Formatting commits are added to `.git-blame-ignore-revs` to reduce noise. - Developers remain free to format code however they prefer locally.
315 lines
10 KiB
C
315 lines
10 KiB
C
/* lmcry_gcry.c
|
|
*
|
|
* An implementation of the cryprov interface for libgcrypt.
|
|
*
|
|
* Copyright 2013-2017 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 <errno.h>
|
|
|
|
#include "module-template.h"
|
|
#include "glbl.h"
|
|
#include "errmsg.h"
|
|
#include "cryprov.h"
|
|
#include "parserif.h"
|
|
#include "libgcry.h"
|
|
#include "lmcry_gcry.h"
|
|
#include "libcry_common.h"
|
|
|
|
MODULE_TYPE_LIB
|
|
MODULE_TYPE_NOKEEP;
|
|
|
|
/* static data */
|
|
DEFobjStaticHelpers;
|
|
DEFobjCurrIf(glbl)
|
|
|
|
/* tables for interfacing with the v6 config system */
|
|
static struct cnfparamdescr cnfpdescrRegular[] = {{"cry.key", eCmdHdlrGetWord, 0},
|
|
{"cry.keyfile", eCmdHdlrGetWord, 0},
|
|
{"cry.keyprogram", eCmdHdlrGetWord, 0},
|
|
{"cry.mode", eCmdHdlrGetWord, 0}, /* CBC, ECB, etc */
|
|
{"cry.algo", eCmdHdlrGetWord, 0}};
|
|
static struct cnfparamblk pblkRegular = {CNFPARAMBLK_VERSION, sizeof(cnfpdescrRegular) / sizeof(struct cnfparamdescr),
|
|
cnfpdescrRegular};
|
|
|
|
static struct cnfparamdescr cnfpdescrQueue[] = {{"queue.cry.key", eCmdHdlrGetWord, 0},
|
|
{"queue.cry.keyfile", eCmdHdlrGetWord, 0},
|
|
{"queue.cry.keyprogram", eCmdHdlrGetWord, 0},
|
|
{"queue.cry.mode", eCmdHdlrGetWord, 0}, /* CBC, ECB, etc */
|
|
{"queue.cry.algo", eCmdHdlrGetWord, 0}};
|
|
static struct cnfparamblk pblkQueue = {CNFPARAMBLK_VERSION, sizeof(cnfpdescrQueue) / sizeof(struct cnfparamdescr),
|
|
cnfpdescrQueue};
|
|
|
|
|
|
#if 0
|
|
static void
|
|
errfunc(__attribute__((unused)) void *usrptr, uchar *emsg)
|
|
{
|
|
LogError(0, RS_RET_CRYPROV_ERR, "Crypto Provider"
|
|
"Error: %s - disabling encryption", emsg);
|
|
}
|
|
#endif
|
|
|
|
/* Standard-Constructor
|
|
*/
|
|
BEGINobjConstruct(lmcry_gcry)
|
|
CHKmalloc(pThis->ctx = gcryCtxNew());
|
|
finalize_it:
|
|
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);
|
|
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.
|
|
*/
|
|
static rsRetVal SetCnfParam(void *pT, struct nvlst *lst, int paramType) {
|
|
lmcry_gcry_t *pThis = (lmcry_gcry_t *)pT;
|
|
int i, r;
|
|
unsigned keylen = 0;
|
|
uchar *key = NULL;
|
|
uchar *keyfile = NULL;
|
|
uchar *keyprogram = NULL;
|
|
uchar *algo = NULL;
|
|
uchar *mode = NULL;
|
|
int nKeys; /* number of keys (actually methods) specified */
|
|
struct cnfparamvals *pvals;
|
|
struct cnfparamblk *pblk;
|
|
DEFiRet;
|
|
|
|
pblk = (paramType == CRYPROV_PARAMTYPE_REGULAR) ? &pblkRegular : &pblkQueue;
|
|
nKeys = 0;
|
|
pvals = nvlstGetParams(lst, pblk, NULL);
|
|
if (pvals == NULL) {
|
|
parser_errmsg("error crypto provider gcryconfig parameters]");
|
|
ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
|
|
}
|
|
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 (!strcmp(pblk->descr[i].name, "cry.key") || !strcmp(pblk->descr[i].name, "queue.cry.key")) {
|
|
key = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL);
|
|
++nKeys;
|
|
} else if (!strcmp(pblk->descr[i].name, "cry.keyfile") || !strcmp(pblk->descr[i].name, "queue.cry.keyfile")) {
|
|
keyfile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL);
|
|
++nKeys;
|
|
} else if (!strcmp(pblk->descr[i].name, "cry.keyprogram") ||
|
|
!strcmp(pblk->descr[i].name, "queue.cry.keyprogram")) {
|
|
keyprogram = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL);
|
|
++nKeys;
|
|
} else if (!strcmp(pblk->descr[i].name, "cry.mode") || !strcmp(pblk->descr[i].name, "queue.cry.mode")) {
|
|
mode = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL);
|
|
} else if (!strcmp(pblk->descr[i].name, "cry.algo") || !strcmp(pblk->descr[i].name, "queue.cry.algo")) {
|
|
algo = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL);
|
|
} else {
|
|
DBGPRINTF(
|
|
"lmcry_gcry: program error, non-handled "
|
|
"param '%s'\n",
|
|
pblk->descr[i].name);
|
|
}
|
|
}
|
|
if (algo != NULL) {
|
|
iRet = rsgcrySetAlgo(pThis->ctx, algo);
|
|
if (iRet != RS_RET_OK) {
|
|
LogError(0, iRet, "cry.algo '%s' is not know/supported", algo);
|
|
FINALIZE;
|
|
}
|
|
}
|
|
if (mode != NULL) {
|
|
iRet = rsgcrySetMode(pThis->ctx, mode);
|
|
if (iRet != RS_RET_OK) {
|
|
LogError(0, iRet, "cry.mode '%s' is not know/supported", mode);
|
|
FINALIZE;
|
|
}
|
|
}
|
|
/* note: key must be set AFTER algo/mode is set (as it depends on them) */
|
|
if (nKeys != 1) {
|
|
LogError(0, RS_RET_INVALID_PARAMS,
|
|
"excactly one of the following "
|
|
"parameters can be specified: cry.key, cry.keyfile, cry.keyprogram\n");
|
|
ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
|
|
}
|
|
if (key != NULL) {
|
|
LogError(0, RS_RET_ERR,
|
|
"Note: specifying an actual key directly from the "
|
|
"config file is highly insecure - DO NOT USE FOR PRODUCTION");
|
|
keylen = strlen((char *)key);
|
|
}
|
|
if (keyfile != NULL) {
|
|
r = cryGetKeyFromFile((char *)keyfile, (char **)&key, &keylen);
|
|
if (r != 0) {
|
|
LogError(errno, RS_RET_ERR, "error reading keyfile %s", keyfile);
|
|
ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
|
|
}
|
|
}
|
|
if (keyprogram != NULL) {
|
|
r = cryGetKeyFromProg((char *)keyprogram, (char **)&key, &keylen);
|
|
if (r != 0) {
|
|
LogError(0, RS_RET_ERR, "error %d obtaining key from program %s\n", r, keyprogram);
|
|
ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
|
|
}
|
|
}
|
|
|
|
/* if we reach this point, we have a valid key */
|
|
r = rsgcrySetKey(pThis->ctx, key, keylen);
|
|
if (r > 0) {
|
|
LogError(0, RS_RET_INVALID_PARAMS,
|
|
"Key length %d expected, but "
|
|
"key of length %d given",
|
|
r, keylen);
|
|
ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
|
|
}
|
|
|
|
finalize_it:
|
|
free(key);
|
|
free(keyfile);
|
|
free(algo);
|
|
free(keyprogram);
|
|
free(mode);
|
|
if (pvals != NULL) cnfparamvalsDestruct(pvals, pblk);
|
|
RETiRet;
|
|
}
|
|
|
|
static void SetDeleteOnClose(void *pF, int val) {
|
|
gcryfileSetDeleteOnClose(pF, val);
|
|
}
|
|
|
|
static rsRetVal GetBytesLeftInBlock(void *pF, ssize_t *left) {
|
|
return gcryfileGetBytesLeftInBlock((gcryfile)pF, left);
|
|
}
|
|
|
|
static rsRetVal DeleteStateFiles(uchar *logfn) {
|
|
return gcryfileDeleteState(logfn);
|
|
}
|
|
|
|
static rsRetVal OnFileOpen(void *pT, uchar *fn, void *pGF, char openMode) {
|
|
lmcry_gcry_t *pThis = (lmcry_gcry_t *)pT;
|
|
gcryfile *pgf = (gcryfile *)pGF;
|
|
DEFiRet;
|
|
DBGPRINTF("lmcry_gcry: open file '%s', mode '%c'\n", fn, openMode);
|
|
|
|
iRet = rsgcryInitCrypt(pThis->ctx, pgf, fn, openMode);
|
|
if (iRet != RS_RET_OK) {
|
|
LogError(0, iRet,
|
|
"Encryption Provider"
|
|
"Error: cannot open .encinfo file - disabling log file");
|
|
}
|
|
RETiRet;
|
|
}
|
|
|
|
static rsRetVal Decrypt(void *pF, uchar *rec, size_t *lenRec) {
|
|
DEFiRet;
|
|
iRet = rsgcryDecrypt(pF, rec, lenRec);
|
|
|
|
RETiRet;
|
|
}
|
|
|
|
|
|
static rsRetVal Encrypt(void *pF, uchar *rec, size_t *lenRec) {
|
|
DEFiRet;
|
|
iRet = rsgcryEncrypt(pF, rec, lenRec);
|
|
|
|
RETiRet;
|
|
}
|
|
|
|
static rsRetVal OnFileClose(void *pF, off64_t offsLogfile) {
|
|
DEFiRet;
|
|
gcryfileDestruct(pF, offsLogfile);
|
|
|
|
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->SetDeleteOnClose = SetDeleteOnClose;
|
|
pIf->Destruct = (rsRetVal(*)(void *))lmcry_gcryDestruct;
|
|
pIf->OnFileOpen = OnFileOpen;
|
|
pIf->Encrypt = Encrypt;
|
|
pIf->Decrypt = Decrypt;
|
|
pIf->OnFileClose = OnFileClose;
|
|
pIf->DeleteStateFiles = DeleteStateFiles;
|
|
pIf->GetBytesLeftInBlock = GetBytesLeftInBlock;
|
|
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(glbl, CORE_COMPONENT);
|
|
|
|
rsgcryExit();
|
|
ENDObjClassExit(lmcry_gcry)
|
|
|
|
|
|
BEGINObjClassInit(lmcry_gcry, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
|
|
/* request objects we use */
|
|
CHKiRet(objUse(glbl, CORE_COMPONENT));
|
|
|
|
if (rsgcryInit() != 0) {
|
|
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
|