summaryrefslogtreecommitdiffstats
path: root/server/parser
diff options
context:
space:
mode:
authorDavid Sommerseth <davids@redhat.com>2009-11-10 10:34:34 +0100
committerDavid Sommerseth <davids@redhat.com>2009-11-10 10:34:34 +0100
commitea59cb6ca1b078af6a33d4c513ff4559197a362a (patch)
treef82fc850502adf4ee8008381776d4e8168718f57 /server/parser
parent395a47412e9727a9ceb63aa7e2186f92783fd862 (diff)
Added new config parameter: max_report_size
To avoid potential DoS attacks by sending big XML files, the max_report_size rejects reports which is bigger than this value. The default value is 2MB if this value is not configured. A new status code was introduced, STAT_FTOOBIG (12). The submissionqueue record will be updated with this value on records which fails this check. In addition minor SIGSEGV failure was fixed when rteval_parserd shutsdown before worker threads have really started.
Diffstat (limited to 'server/parser')
-rw-r--r--server/parser/configparser.c1
-rw-r--r--server/parser/parsethread.c45
-rw-r--r--server/parser/pgsql.c3
-rw-r--r--server/parser/rteval_parserd.c11
-rw-r--r--server/parser/statuses.h1
-rw-r--r--server/parser/threadinfo.h1
6 files changed, 55 insertions, 7 deletions
diff --git a/server/parser/configparser.c b/server/parser/configparser.c
index 1e68d23..3cad827 100644
--- a/server/parser/configparser.c
+++ b/server/parser/configparser.c
@@ -118,6 +118,7 @@ static inline eurephiaVALUES *default_cfg_values(LogContext *log, eurephiaVALUES
eAdd_value(cfg, "db_username", "rtevparser");
eAdd_value(cfg, "db_password", "rtevaldb_parser");
eAdd_value(cfg, "reportdir", "/var/lib/rteval/reports");
+ eAdd_value(cfg, "max_report_size", "2097152"); // 2MB
// Copy over the arguments to the config, update existing settings
for( ptr = prgargs; ptr; ptr = ptr->next ) {
diff --git a/server/parser/parsethread.c b/server/parser/parsethread.c
index fbf6777..7e4f89a 100644
--- a/server/parser/parsethread.c
+++ b/server/parser/parsethread.c
@@ -136,10 +136,38 @@ static char *get_destination_path(LogContext *log, const char *destdir,
/**
+ * Checks if the file size of the given file is below the given max size value.
+ *
+ * @param log Log context
+ * @param fname Filename to the file to check
+ * @param maxsize Maximum allowed file size
+ *
+ * @return Returns 1 if file is within the limit, otherwise 0. On errors -1 is returned.
+ */
+inline int check_filesize(LogContext *log, const char *fname, unsigned int maxsize) {
+ struct stat info;
+
+ if( !fname ) {
+ return 0;
+ }
+
+ errno = 0;
+ if( (stat(fname, &info) < 0) ) {
+ writelog(log, LOG_ERR, "Failed to check report file '%s': %s",
+ fname, strerror(errno));
+ return -1;
+ }
+
+ return (info.st_size <= maxsize);
+}
+
+
+/**
* The core parse function. Parses an XML file and stores it in the database according to
* the xmlparser.xsl template.
*
* @param dbc Database connection
+ * @param max_fsize Maximum "allowed" file size for reports to be parsed
* @param xslt Pointer to a parsed XSLT Stylesheet (xmlparser.xsl)
* @param mtx_sysreg Mutex locking to avoid simultaneous registration of systems, as they cannot
* be in an SQL transaction (due to SHA1 sysid must be registered and visible ASAP)
@@ -149,6 +177,7 @@ static char *get_destination_path(LogContext *log, const char *destdir,
* @return Return values:
* @code
* STAT_SUCCESS : Successfully registered report
+ * STAT_FTOOBIG : XML report file is too big
* STAT_XMLFAIL : Could not parse the XML report file
* STAT_SYSREG : Failed to register the system into the systems or systems_hostname tables
* STAT_RTERIDREG: Failed to get a new rterid value
@@ -158,13 +187,21 @@ static char *get_destination_path(LogContext *log, const char *destdir,
* STAT_REPMOVE : Failed to move the report file
* @endcode
*/
-inline int parse_report(dbconn *dbc, xsltStylesheet *xslt, pthread_mutex_t *mtx_sysreg,
- const char *destdir, parseJob_t *job) {
+inline int parse_report(dbconn *dbc, unsigned int max_fsize, xsltStylesheet *xslt,
+ pthread_mutex_t *mtx_sysreg, const char *destdir, parseJob_t *job)
+{
int syskey = -1, rterid = -1;
int rc = -1;
xmlDoc *repxml = NULL;
char *destfname;
+ // Check file size - and reject too big files
+ if( check_filesize(dbc->log, job->filename, max_fsize) == 0 ) {
+ writelog(dbc->log, LOG_ERR, "Report file '%s' is too big, rejected", job->filename);
+ return STAT_FTOOBIG;
+ }
+
+
repxml = xmlParseFile(job->filename);
if( !repxml ) {
writelog(dbc->log, LOG_ERR,
@@ -316,8 +353,8 @@ void *parsethread(void *thrargs) {
// Mark the job as "in progress", if successful update, continue parsing it
if( db_update_submissionqueue(args->dbc, jobinfo.submid, STAT_INPROG) ) {
- res = parse_report(args->dbc, args->xslt, args->mtx_sysreg,
- args->destdir, &jobinfo);
+ res = parse_report(args->dbc, args->max_report_size, args->xslt,
+ args->mtx_sysreg, args->destdir, &jobinfo);
// Set the status for the submission
db_update_submissionqueue(args->dbc, jobinfo.submid, res);
} else {
diff --git a/server/parser/pgsql.c b/server/parser/pgsql.c
index 0016761..c59fbe1 100644
--- a/server/parser/pgsql.c
+++ b/server/parser/pgsql.c
@@ -630,6 +630,8 @@ int db_update_submissionqueue(dbconn *dbc, unsigned int submid, int status) {
case STAT_ASSIGNED:
case STAT_RTERIDREG:
case STAT_REPMOVE:
+ case STAT_XMLFAIL:
+ case STAT_FTOOBIG:
snprintf(sql, 4096,
"UPDATE submissionqueue SET status = %i"
" WHERE submid = %i", status, submid);
@@ -643,7 +645,6 @@ int db_update_submissionqueue(dbconn *dbc, unsigned int submid, int status) {
case STAT_SUCCESS:
case STAT_UNKNFAIL:
- case STAT_XMLFAIL:
case STAT_SYSREG:
case STAT_GENDB:
case STAT_RTEVRUNS:
diff --git a/server/parser/rteval_parserd.c b/server/parser/rteval_parserd.c
index a075ff0..ddd7b6a 100644
--- a/server/parser/rteval_parserd.c
+++ b/server/parser/rteval_parserd.c
@@ -306,6 +306,7 @@ int main(int argc, char **argv) {
struct mq_attr msgq_attr;
mqd_t msgq = 0;
int i,rc, mq_init = 0, max_threads = 0, started_threads = 0, activethreads = 0;
+ unsigned int max_report_size = 0;
// Initialise XML and XSLT libraries
xsltInit();
@@ -386,6 +387,7 @@ int main(int argc, char **argv) {
reportdir = eGet_value(config, "reportdir");
writelog(logctx, LOG_INFO, "Starting %i worker threads", max_threads);
+ max_report_size = defaultIntValue(atoi_nullsafe(eGet_value(config, "max_report_size")), 1024*1024);
for( i = 0; i < max_threads; i++ ) {
// Prepare thread specific data
thrdata[i] = malloc_nullsafe(logctx, sizeof(threadData_t));
@@ -414,6 +416,7 @@ int main(int argc, char **argv) {
thrdata[i]->mtx_sysreg = &mtx_sysreg;
thrdata[i]->xslt = xslt;
thrdata[i]->destdir = reportdir;
+ thrdata[i]->max_report_size = max_report_size;
thread_attrs[i] = malloc_nullsafe(logctx, sizeof(pthread_attr_t));
if( !thread_attrs[i] ) {
@@ -478,8 +481,12 @@ int main(int argc, char **argv) {
}
pthread_attr_destroy(thread_attrs[i]);
}
- free_nullsafe(threads[i]);
- free_nullsafe(thread_attrs[i]);
+ if( threads ) {
+ free_nullsafe(threads[i]);
+ }
+ if( thread_attrs ) {
+ free_nullsafe(thread_attrs[i]);
+ }
// Disconnect threads database connection
if( thrdata && thrdata[i] ) {
diff --git a/server/parser/statuses.h b/server/parser/statuses.h
index 701c8e8..6edeac6 100644
--- a/server/parser/statuses.h
+++ b/server/parser/statuses.h
@@ -35,5 +35,6 @@
#define STAT_RTEVRUNS 9 /**< Registering rteval run information failed */
#define STAT_CYCLIC 10 /**< Registering cyclictest results failed */
#define STAT_REPMOVE 11 /**< Failed to move the report file */
+#define STAT_FTOOBIG 12 /**< Report is too big (see config parameter: max_report_size) */
#endif
diff --git a/server/parser/threadinfo.h b/server/parser/threadinfo.h
index d2bcf43..d007e9f 100644
--- a/server/parser/threadinfo.h
+++ b/server/parser/threadinfo.h
@@ -39,6 +39,7 @@ typedef struct {
dbconn *dbc; /**< Database connection assigned to this thread */
xsltStylesheet *xslt; /**< XSLT stylesheet assigned to this thread */
const char *destdir; /**< Directory where to put the parsed reports */
+ unsigned int max_report_size; /**< Maximum accepted file size of reports (config: max_report_size) */
} threadData_t;
#endif