diff options
| author | David Sommerseth <davids@redhat.com> | 2009-11-10 10:34:34 +0100 |
|---|---|---|
| committer | David Sommerseth <davids@redhat.com> | 2009-11-10 10:34:34 +0100 |
| commit | ea59cb6ca1b078af6a33d4c513ff4559197a362a (patch) | |
| tree | f82fc850502adf4ee8008381776d4e8168718f57 /server/parser | |
| parent | 395a47412e9727a9ceb63aa7e2186f92783fd862 (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.c | 1 | ||||
| -rw-r--r-- | server/parser/parsethread.c | 45 | ||||
| -rw-r--r-- | server/parser/pgsql.c | 3 | ||||
| -rw-r--r-- | server/parser/rteval_parserd.c | 11 | ||||
| -rw-r--r-- | server/parser/statuses.h | 1 | ||||
| -rw-r--r-- | server/parser/threadinfo.h | 1 |
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 |
