diff options
Diffstat (limited to 'tools/omfile.c')
-rw-r--r-- | tools/omfile.c | 69 |
1 files changed, 56 insertions, 13 deletions
diff --git a/tools/omfile.c b/tools/omfile.c index 0f476000..f7339300 100644 --- a/tools/omfile.c +++ b/tools/omfile.c @@ -16,7 +16,7 @@ * pipes. These have been moved to ompipe, to reduced the entanglement * between the two different functionalities. -- rgerhards * - * Copyright 2007-2009 Rainer Gerhards and Adiscon GmbH. + * Copyright 2007-2011 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * @@ -87,12 +87,15 @@ typedef struct s_dynaFileCacheEntry dynaFileCacheEntry; #define IOBUF_DFLT_SIZE 1024 /* default size for io buffers */ #define FLUSH_INTRVL_DFLT 1 /* default buffer flush interval (in seconds) */ #define USE_ASYNCWRITER_DFLT 0 /* default buffer use async writer */ +#define FLUSHONTX_DFLT 1 /* default for flush on TX end */ +#define DFLT_bForceChown 0 /* globals for default values */ static int iDynaFileCacheSize = 10; /* max cache for dynamic files */ static int fCreateMode = 0644; /* mode to use when creating files */ static int fDirCreateMode = 0700; /* mode to use when creating files */ static int bFailOnChown; /* fail if chown fails? */ +static int bForceChown = DFLT_bForceChown; /* Force chown() on existing files? */ static uid_t fileUID; /* UID to be used for newly created files */ static uid_t fileGID; /* GID to be used for newly created files */ static uid_t dirUID; /* UID to be used for newly created directories */ @@ -100,7 +103,7 @@ static uid_t dirGID; /* GID to be used for newly created directories */ static int bCreateDirs = 1;/* auto-create directories for dynaFiles: 0 - no, 1 - yes */ static int bEnableSync = 0;/* enable syncing of files (no dash in front of pathname in conf): 0 - no, 1 - yes */ static int iZipLevel = 0; /* zip compression mode (0..9 as usual) */ -static bool bFlushOnTXEnd = 0;/* flush write buffers when transaction has ended? */ +static bool bFlushOnTXEnd = FLUSHONTX_DFLT;/* flush write buffers when transaction has ended? */ static int64 iIOBufSize = IOBUF_DFLT_SIZE; /* size of an io buffer */ static int iFlushInterval = FLUSH_INTRVL_DFLT; /* how often flush the output buffer on inactivity? */ static int bUseAsyncWriter = USE_ASYNCWRITER_DFLT; /* should we enable asynchronous writing? */ @@ -117,6 +120,7 @@ typedef struct _instanceData { int fDirCreateMode; /* creation mode for mkdir() */ int bCreateDirs; /* auto-create directories? */ int bSyncFile; /* should the file by sync()'ed? 1- yes, 0- no */ + bool bForceChown; /* force chown() on existing files? */ uid_t fileUID; /* IDs for creation */ uid_t dirUID; gid_t fileGID; @@ -162,8 +166,9 @@ CODESTARTdbgPrintInstInfo dbgprintf("\tflush interval=%d\n", pData->iFlushInterval); dbgprintf("\tfile cache size=%d\n", pData->iDynaFileCacheSize); dbgprintf("\tcreate directories: %s\n", pData->bCreateDirs ? "yes" : "no"); - dbgprintf("\tfile owner %d, group %d\n", pData->fileUID, pData->fileGID); - dbgprintf("\tdirectory owner %d, group %d\n", pData->dirUID, pData->dirGID); + dbgprintf("\tfile owner %d, group %d\n", (int) pData->fileUID, (int) pData->fileGID); + dbgprintf("\tforce chown() for all files: %s\n", pData->bForceChown ? "yes" : "no"); + dbgprintf("\tdirectory owner %d, group %d\n", (int) pData->dirUID, (int) pData->dirGID); dbgprintf("\tdir create mode 0%3.3o, file create mode 0%3.3o\n", pData->fDirCreateMode, pData->fCreateMode); dbgprintf("\tfail if owner/group can not be set: %s\n", pData->bFailOnChown ? "yes" : "no"); @@ -350,9 +355,24 @@ prepareFile(instanceData *pData, uchar *newFileName) int fd; DEFiRet; - if(access((char*)newFileName, F_OK) != 0) { + pData->pStrm = NULL; + if(access((char*)newFileName, F_OK) == 0) { + if(pData->bForceChown) { + /* Try to fix wrong ownership set by someone else. Note that this code + * will no longer work once we have made the $PrivDrop code fully secure. + * This change is based on an idea of Michael Terry, provided as part of + * the effort to make rsyslogd the Ubuntu default syslogd. + * rgerhards, 2009-09-11 + */ + if(chown((char*)newFileName, pData->fileUID, pData->fileGID) != 0) { + if(pData->bFailOnChown) { + int eSave = errno; + errno = eSave; + } + } + } + } else { /* file does not exist, create it (and eventually parent directories */ - fd = -1; if(pData->bCreateDirs) { /* We first need to create parent dirs if they are missing. * We do not report any errors here ourselfs but let the code @@ -371,7 +391,7 @@ prepareFile(instanceData *pData, uchar *newFileName) pData->fCreateMode); if(fd != -1) { /* check and set uid/gid */ - if(pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) { + if(pData->bForceChown || pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) { /* we need to set owner/group */ if(fchown(fd, pData->fileUID, pData->fileGID) != 0) { if(pData->bFailOnChown) { @@ -421,6 +441,11 @@ prepareFile(instanceData *pData, uchar *newFileName) CHKiRet(strm.ConstructFinalize(pData->pStrm)); finalize_it: + if(iRet != RS_RET_OK) { + if(pData->pStrm != NULL) { + strm.Destruct(&pData->pStrm); + } + } RETiRet; } @@ -497,7 +522,7 @@ prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts) pData->iCurrElt = -1; /* similarly, we need to set the current pStrm to NULL, because otherwise, if prepareFile() fails, * we may end up using an old stream. This bug depends on how exactly prepareFile fails, - * but it* could be triggered in the common case of a failed open() system call. + * but it could be triggered in the common case of a failed open() system call. * rgerhards, 2010-03-22 */ pData->pStrm = NULL; @@ -526,8 +551,8 @@ prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts) /* Ok, we finally can open the file */ localRet = prepareFile(pData, newFileName); /* ignore exact error, we check fd below */ - /* file is either open now or an error state set */ // RG: better check localRet? - if(pData->pStrm == NULL) { + /* check if we had an error */ + if(localRet != RS_RET_OK) { /* do not report anything if the message is an internally-generated * message. Otherwise, we could run into a never-ending loop. The bad * news is that we also lose errors on startup messages, but so it is. @@ -535,7 +560,7 @@ prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts) if(iMsgOpts & INTERNAL_MSG) { DBGPRINTF("Could not open dynaFile, discarding message\n"); } else { - errmsg.LogError(0, NO_ERRCODE, "Could not open dynamic file '%s' - discarding message", newFileName); + errmsg.LogError(0, NO_ERRCODE, "Could not open dynamic file '%s' [state %d] - discarding message", newFileName, localRet); } ABORT_FINALIZE(localRet); } @@ -646,6 +671,21 @@ ENDdoAction BEGINparseSelectorAct CODESTARTparseSelectorAct + /* Note: the indicator sequence permits us to use '$' to signify + * outchannel, what otherwise is not possible due to truely + * unresolvable grammar conflicts (*this time no way around*). + * rgerhards, 2011-07-09 + */ + if(!strncmp((char*) p, ":omfile:", sizeof(":omfile:") - 1)) { + p += sizeof(":omfile:") - 1; + } else { + if(*p == '$') { + errmsg.LogError(0, RS_RET_OUTDATED_STMT, + "action '%s' treated as ':omfile:%s' - please " + "change syntax, '%s' will not be supported in " + "rsyslog v6 and above.", p, p, p); + } + } if(!(*p == '$' || *p == '?' || *p == '/' || *p == '.' || *p == '-')) ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); @@ -723,6 +763,7 @@ CODESTARTparseSelectorAct pData->fDirCreateMode = fDirCreateMode; pData->bCreateDirs = bCreateDirs; pData->bFailOnChown = bFailOnChown; + pData->bForceChown = bForceChown; pData->fileUID = fileUID; pData->fileGID = fileGID; pData->dirUID = dirUID; @@ -741,7 +782,7 @@ CODESTARTparseSelectorAct if(pData->pStrm == NULL) { DBGPRINTF("Error opening log file: %s\n", pData->f_fname); - errmsg.LogError(0, RS_RET_NO_FILE_ACCESS, "Could no open output file '%s'", pData->f_fname); + errmsg.LogError(0, RS_RET_NO_FILE_ACCESS, "Could not open output file '%s'", pData->f_fname); } } CODE_STD_FINALIZERparseSelectorAct @@ -758,13 +799,14 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a dirUID = -1; dirGID = -1; bFailOnChown = 1; + bForceChown = DFLT_bForceChown; iDynaFileCacheSize = 10; fCreateMode = 0644; fDirCreateMode = 0700; bCreateDirs = 1; bEnableSync = 0; iZipLevel = 0; - bFlushOnTXEnd = 0; + bFlushOnTXEnd = FLUSHONTX_DFLT; iIOBufSize = IOBUF_DFLT_SIZE; iFlushInterval = FLUSH_INTRVL_DFLT; bUseAsyncWriter = USE_ASYNCWRITER_DFLT; @@ -825,6 +867,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(omsdRegCFSLineHdlr((uchar *)"filecreatemode", 0, eCmdHdlrFileCreateMode, NULL, &fCreateMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"createdirs", 0, eCmdHdlrBinary, NULL, &bCreateDirs, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"failonchownfailure", 0, eCmdHdlrBinary, NULL, &bFailOnChown, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileForceChown", 0, eCmdHdlrBinary, NULL, &bForceChown, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfileenablesync", 0, eCmdHdlrBinary, NULL, &bEnableSync, STD_LOADABLE_MODULE_ID)); CHKiRet(regCfSysLineHdlr((uchar *)"actionfiledefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszFileDfltTplName, NULL)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); |