config: Apply more strict input validation to almost all config file options

Signed-off-by: Ken ICHIKAWA <ichikawa.ken@jp.fujitsu.com>
master
Ken ICHIKAWA 2013-06-10 16:16:26 +09:00 committed by Richard Cochran
parent 67c925f459
commit 0513c3b15b
1 changed files with 128 additions and 93 deletions

221
config.c
View File

@ -16,9 +16,11 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h>
#include "config.h" #include "config.h"
#include "ether.h" #include "ether.h"
#include "print.h" #include "print.h"
@ -53,77 +55,90 @@ static enum parser_result parse_pod_setting(const char *option,
struct port_defaults *pod) struct port_defaults *pod)
{ {
int val; int val;
Integer8 i8; unsigned int uval;
UInteger8 u8;
enum parser_result r;
if (!strcmp(option, "delayAsymmetry")) { if (!strcmp(option, "delayAsymmetry")) {
if (1 != sscanf(value, "%d", &val)) r = get_ranged_int(value, &val, INT_MIN, INT_MAX);
return BAD_VALUE; if (r != PARSED_OK)
return r;
pod->asymmetry = (Integer64) val << 16; pod->asymmetry = (Integer64) val << 16;
} else if (!strcmp(option, "logAnnounceInterval")) { } else if (!strcmp(option, "logAnnounceInterval")) {
if (1 != sscanf(value, "%hhd", &i8)) r = get_ranged_int(value, &val, INT8_MIN, INT8_MAX);
return BAD_VALUE; if (r != PARSED_OK)
pod->logAnnounceInterval = i8; return r;
pod->logAnnounceInterval = val;
} else if (!strcmp(option, "logSyncInterval")) { } else if (!strcmp(option, "logSyncInterval")) {
if (1 != sscanf(value, "%hhd", &i8)) r = get_ranged_int(value, &val, INT8_MIN, INT8_MAX);
return BAD_VALUE; if (r != PARSED_OK)
pod->logSyncInterval = i8; return r;
pod->logSyncInterval = val;
} else if (!strcmp(option, "logMinDelayReqInterval")) { } else if (!strcmp(option, "logMinDelayReqInterval")) {
if (1 != sscanf(value, "%hhd", &i8)) r = get_ranged_int(value, &val, INT8_MIN, INT8_MAX);
return BAD_VALUE; if (r != PARSED_OK)
pod->logMinDelayReqInterval = i8; return r;
pod->logMinDelayReqInterval = val;
} else if (!strcmp(option, "logMinPdelayReqInterval")) { } else if (!strcmp(option, "logMinPdelayReqInterval")) {
if (1 != sscanf(value, "%hhd", &i8)) r = get_ranged_int(value, &val, INT8_MIN, INT8_MAX);
return BAD_VALUE; if (r != PARSED_OK)
pod->logMinPdelayReqInterval = i8; return r;
pod->logMinPdelayReqInterval = val;
} else if (!strcmp(option, "announceReceiptTimeout")) { } else if (!strcmp(option, "announceReceiptTimeout")) {
if (1 != sscanf(value, "%hhu", &u8)) r = get_ranged_uint(value, &uval, 0, UINT8_MAX);
return BAD_VALUE; if (r != PARSED_OK)
pod->announceReceiptTimeout = u8; return r;
pod->announceReceiptTimeout = uval;
} else if (!strcmp(option, "transportSpecific")) { } else if (!strcmp(option, "transportSpecific")) {
if (1 != sscanf(value, "%hhx", &u8)) r = get_ranged_uint(value, &uval, 0, 0x0F);
return BAD_VALUE; if (r != PARSED_OK)
pod->transportSpecific = u8 << 4; return r;
pod->transportSpecific = uval << 4;
} else if (!strcmp(option, "path_trace_enabled")) { } else if (!strcmp(option, "path_trace_enabled")) {
if (1 != sscanf(value, "%u", &val)) r = get_ranged_int(value, &val, 0, 1);
return BAD_VALUE; if (r != PARSED_OK)
pod->path_trace_enabled = val ? 1 : 0; return r;
pod->path_trace_enabled = val;
} else if (!strcmp(option, "follow_up_info")) { } else if (!strcmp(option, "follow_up_info")) {
if (1 != sscanf(value, "%u", &val)) r = get_ranged_int(value, &val, 0, 1);
return BAD_VALUE; if (r != PARSED_OK)
pod->follow_up_info = val ? 1 : 0; return r;
pod->follow_up_info = val;
} else if (!strcmp(option, "neighborPropDelayThresh")) { } else if (!strcmp(option, "neighborPropDelayThresh")) {
if (1 != sscanf(value, "%d", &val)) r = get_ranged_uint(value, &uval, 0, UINT32_MAX);
return BAD_VALUE; if (r != PARSED_OK)
pod->neighborPropDelayThresh = val; return r;
pod->neighborPropDelayThresh = uval;
} else if (!strcmp(option, "fault_badpeernet_interval")) { } else if (!strcmp(option, "fault_badpeernet_interval")) {
pod->flt_interval_pertype[FT_BAD_PEER_NETWORK].type = FTMO_LINEAR_SECONDS; pod->flt_interval_pertype[FT_BAD_PEER_NETWORK].type = FTMO_LINEAR_SECONDS;
if (!strcasecmp("ASAP", value)) { if (!strcasecmp("ASAP", value)) {
pod->flt_interval_pertype[FT_BAD_PEER_NETWORK].val = 0; pod->flt_interval_pertype[FT_BAD_PEER_NETWORK].val = 0;
} else if (1 == sscanf(value, "%d", &val)) {
pod->flt_interval_pertype[FT_BAD_PEER_NETWORK].val = val;
} else { } else {
return BAD_VALUE; r = get_ranged_int(value, &val, INT32_MIN, INT32_MAX);
if (r != PARSED_OK)
return r;
pod->flt_interval_pertype[FT_BAD_PEER_NETWORK].val = val;
} }
} else if (!strcmp(option, "fault_reset_interval")) { } else if (!strcmp(option, "fault_reset_interval")) {
pod->flt_interval_pertype[FT_UNSPECIFIED].type = FTMO_LOG2_SECONDS; pod->flt_interval_pertype[FT_UNSPECIFIED].type = FTMO_LOG2_SECONDS;
if (!strcasecmp("ASAP", value)) { if (!strcasecmp("ASAP", value)) {
pod->flt_interval_pertype[FT_UNSPECIFIED].val = FRI_ASAP; pod->flt_interval_pertype[FT_UNSPECIFIED].val = FRI_ASAP;
} else if (1 == sscanf(value, "%hhd", &i8)) {
pod->flt_interval_pertype[FT_UNSPECIFIED].val = i8;
} else { } else {
return BAD_VALUE; r = get_ranged_int(value, &val, INT8_MIN, INT8_MAX);
if (r != PARSED_OK)
return r;
pod->flt_interval_pertype[FT_UNSPECIFIED].val = val;
} }
} else } else
@ -185,8 +200,7 @@ static enum parser_result parse_global_setting(const char *option,
{ {
double df; double df;
int i, val, cfg_ignore = cfg->cfg_ignore; int i, val, cfg_ignore = cfg->cfg_ignore;
UInteger16 u16; unsigned int uval;
UInteger8 u8;
unsigned char mac[MAC_LEN]; unsigned char mac[MAC_LEN];
unsigned char oui[OUI_LEN]; unsigned char oui[OUI_LEN];
@ -200,16 +214,18 @@ static enum parser_result parse_global_setting(const char *option,
return r; return r;
if (!strcmp(option, "twoStepFlag")) { if (!strcmp(option, "twoStepFlag")) {
if (1 != sscanf(value, "%d", &val)) r = get_ranged_int(value, &val, 0, 1);
return BAD_VALUE; if (r != PARSED_OK)
return r;
if (val) if (val)
dds->flags |= DDS_TWO_STEP_FLAG; dds->flags |= DDS_TWO_STEP_FLAG;
else else
dds->flags &= ~DDS_TWO_STEP_FLAG; dds->flags &= ~DDS_TWO_STEP_FLAG;
} else if (!strcmp(option, "slaveOnly")) { } else if (!strcmp(option, "slaveOnly")) {
if (1 != sscanf(value, "%d", &val)) r = get_ranged_int(value, &val, 0, 1);
return BAD_VALUE; if (r != PARSED_OK)
return r;
if (!(cfg_ignore & CFG_IGNORE_SLAVEONLY)) { if (!(cfg_ignore & CFG_IGNORE_SLAVEONLY)) {
if (val) if (val)
dds->flags |= DDS_SLAVE_ONLY; dds->flags |= DDS_SLAVE_ONLY;
@ -218,75 +234,89 @@ static enum parser_result parse_global_setting(const char *option,
} }
} else if (!strcmp(option, "priority1")) { } else if (!strcmp(option, "priority1")) {
if (1 != sscanf(value, "%hhu", &u8)) r = get_ranged_uint(value, &uval, 0, UINT8_MAX);
return BAD_VALUE; if (r != PARSED_OK)
dds->priority1 = u8; return r;
dds->priority1 = uval;
} else if (!strcmp(option, "priority2")) { } else if (!strcmp(option, "priority2")) {
if (1 != sscanf(value, "%hhu", &u8)) r = get_ranged_uint(value, &uval, 0, UINT8_MAX);
return BAD_VALUE; if (r != PARSED_OK)
dds->priority2 = u8; return r;
dds->priority2 = uval;
} else if (!strcmp(option, "domainNumber")) { } else if (!strcmp(option, "domainNumber")) {
if (1 != sscanf(value, "%hhu", &u8) || u8 > 127) r = get_ranged_uint(value, &uval, 0, 127);
return BAD_VALUE; if (r != PARSED_OK)
dds->domainNumber = u8; return r;
dds->domainNumber = uval;
} else if (!strcmp(option, "clockClass")) { } else if (!strcmp(option, "clockClass")) {
if (1 != sscanf(value, "%hhu", &u8)) r = get_ranged_uint(value, &uval, 0, UINT8_MAX);
return BAD_VALUE; if (r != PARSED_OK)
return r;
if (!(cfg_ignore & CFG_IGNORE_SLAVEONLY)) if (!(cfg_ignore & CFG_IGNORE_SLAVEONLY))
dds->clockQuality.clockClass = u8; dds->clockQuality.clockClass = uval;
} else if (!strcmp(option, "clockAccuracy")) { } else if (!strcmp(option, "clockAccuracy")) {
if (1 != sscanf(value, "%hhx", &u8)) r = get_ranged_uint(value, &uval, 0, UINT8_MAX);
return BAD_VALUE; if (r != PARSED_OK)
dds->clockQuality.clockAccuracy = u8; return r;
dds->clockQuality.clockAccuracy = uval;
} else if (!strcmp(option, "offsetScaledLogVariance")) { } else if (!strcmp(option, "offsetScaledLogVariance")) {
if (1 != sscanf(value, "%hx", &u16)) r = get_ranged_uint(value, &uval, 0, UINT16_MAX);
return BAD_VALUE; if (r != PARSED_OK)
dds->clockQuality.offsetScaledLogVariance = u16; return r;
dds->clockQuality.offsetScaledLogVariance = uval;
} else if (!strcmp(option, "free_running")) { } else if (!strcmp(option, "free_running")) {
if (1 != sscanf(value, "%d", &val)) r = get_ranged_int(value, &val, 0, 1);
return BAD_VALUE; if (r != PARSED_OK)
cfg->dds.free_running = val ? 1 : 0; return r;
cfg->dds.free_running = val;
} else if (!strcmp(option, "freq_est_interval")) { } else if (!strcmp(option, "freq_est_interval")) {
if (1 != sscanf(value, "%d", &val) || val < 0) r = get_ranged_int(value, &val, 0, INT_MAX);
return BAD_VALUE; if (r != PARSED_OK)
return r;
cfg->dds.freq_est_interval = val; cfg->dds.freq_est_interval = val;
pod->freq_est_interval = val; pod->freq_est_interval = val;
} else if (!strcmp(option, "assume_two_step")) { } else if (!strcmp(option, "assume_two_step")) {
if (1 != sscanf(value, "%u", &val)) r = get_ranged_int(value, &val, 0, 1);
return BAD_VALUE; if (r != PARSED_OK)
*cfg->assume_two_step = val ? 1 : 0; return r;
*cfg->assume_two_step = val;
} else if (!strcmp(option, "tx_timestamp_timeout")) { } else if (!strcmp(option, "tx_timestamp_timeout")) {
if (1 != sscanf(value, "%u", &val) || val <= 0) r = get_ranged_int(value, &val, 1, INT_MAX);
return BAD_VALUE; if (r != PARSED_OK)
return r;
*cfg->tx_timestamp_timeout = val; *cfg->tx_timestamp_timeout = val;
} else if (!strcmp(option, "pi_proportional_const")) { } else if (!strcmp(option, "pi_proportional_const")) {
if (1 != sscanf(value, "%lf", &df) || df < 0.0) r = get_ranged_double(value, &df, 0.0, DBL_MAX);
return BAD_VALUE; if (r != PARSED_OK)
return r;
*cfg->pi_proportional_const = df; *cfg->pi_proportional_const = df;
} else if (!strcmp(option, "pi_integral_const")) { } else if (!strcmp(option, "pi_integral_const")) {
if (1 != sscanf(value, "%lf", &df) || df < 0.0) r = get_ranged_double(value, &df, 0.0, DBL_MAX);
return BAD_VALUE; if (r != PARSED_OK)
return r;
*cfg->pi_integral_const = df; *cfg->pi_integral_const = df;
} else if (!strcmp(option, "pi_offset_const")) { } else if (!strcmp(option, "pi_offset_const")) {
if (1 != sscanf(value, "%lf", &df) || df < 0.0) r = get_ranged_double(value, &df, 0.0, DBL_MAX);
return BAD_VALUE; if (r != PARSED_OK)
return r;
*cfg->pi_offset_const = df; *cfg->pi_offset_const = df;
} else if (!strcmp(option, "pi_max_frequency")) { } else if (!strcmp(option, "pi_max_frequency")) {
if (1 != sscanf(value, "%d", &val) || val < 0) r = get_ranged_int(value, &val, 0, INT_MAX);
return BAD_VALUE; if (r != PARSED_OK)
return r;
*cfg->pi_max_frequency = val; *cfg->pi_max_frequency = val;
} else if (!strcmp(option, "ptp_dst_mac")) { } else if (!strcmp(option, "ptp_dst_mac")) {
@ -304,9 +334,10 @@ static enum parser_result parse_global_setting(const char *option,
cfg->p2p_dst_mac[i] = mac[i]; cfg->p2p_dst_mac[i] = mac[i];
} else if (!strcmp(option, "udp6_scope")) { } else if (!strcmp(option, "udp6_scope")) {
if (1 != sscanf(value, "%hhx", &u8) || (u8 & 0xF0)) r = get_ranged_uint(value, &uval, 0x00, 0x0F);
return BAD_VALUE; if (r != PARSED_OK)
*cfg->udp6_scope = u8; return r;
*cfg->udp6_scope = uval;
} else if (!strcmp(option, "logging_level")) { } else if (!strcmp(option, "logging_level")) {
r = get_ranged_int(value, &val, r = get_ranged_int(value, &val,
@ -318,16 +349,18 @@ static enum parser_result parse_global_setting(const char *option,
} }
} else if (!strcmp(option, "verbose")) { } else if (!strcmp(option, "verbose")) {
if (1 != sscanf(value, "%d", &val)) r = get_ranged_int(value, &val, 0, 1);
return BAD_VALUE; if (r != PARSED_OK)
return r;
if (!(cfg_ignore & CFG_IGNORE_VERBOSE)) if (!(cfg_ignore & CFG_IGNORE_VERBOSE))
cfg->verbose = val ? 1 : 0; cfg->verbose = val;
} else if (!strcmp(option, "use_syslog")) { } else if (!strcmp(option, "use_syslog")) {
if (1 != sscanf(value, "%d", &val)) r = get_ranged_int(value, &val, 0, 1);
return BAD_VALUE; if (r != PARSED_OK)
return r;
if (!(cfg_ignore & CFG_IGNORE_USE_SYSLOG)) if (!(cfg_ignore & CFG_IGNORE_USE_SYSLOG))
cfg->use_syslog = val ? 1 : 0; cfg->use_syslog = val;
} else if (!strcmp(option, "time_stamping")) { } else if (!strcmp(option, "time_stamping")) {
if (!(cfg_ignore & CFG_IGNORE_TIMESTAMPING)) { if (!(cfg_ignore & CFG_IGNORE_TIMESTAMPING)) {
@ -395,13 +428,15 @@ static enum parser_result parse_global_setting(const char *option,
cfg->dds.clock_desc.manufacturerIdentity[i] = oui[i]; cfg->dds.clock_desc.manufacturerIdentity[i] = oui[i];
} else if (!strcmp(option, "summary_interval")) { } else if (!strcmp(option, "summary_interval")) {
if (1 != sscanf(value, "%d", &val)) r = get_ranged_int(value, &val, INT_MIN, INT_MAX);
return BAD_VALUE; if (r != PARSED_OK)
return r;
cfg->dds.stats_interval = val; cfg->dds.stats_interval = val;
} else if (!strcmp(option, "kernel_leap")) { } else if (!strcmp(option, "kernel_leap")) {
if (1 != sscanf(value, "%d", &val)) r = get_ranged_int(value, &val, 0, 1);
return BAD_VALUE; if (r != PARSED_OK)
return r;
cfg->dds.kernel_leap = val; cfg->dds.kernel_leap = val;
} else } else