Changeset 7010bc5b07e615c0314ff1c0ebb27bdf8420cca3

Show
Ignore:
Timestamp:
09/16/09 04:19:24 (5 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1253074764 +0000
git-parent:

[6298e33b2e6517913907fa76bd9af5a1ea28b922]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1253074764 +0000
Message:

robust input validation, refs #171

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/noit_check.c

    r914f047 r7010bc5  
    486486} 
    487487 
     488noit_boolean 
     489noit_check_is_valid_target(const char *target) { 
     490  int8_t family; 
     491  int rv; 
     492  union { 
     493    struct in_addr addr4; 
     494    struct in6_addr addr6; 
     495  } a; 
     496 
     497  family = AF_INET; 
     498  rv = inet_pton(family, target, &a); 
     499  if(rv != 1) { 
     500    family = AF_INET6; 
     501    rv = inet_pton(family, target, &a); 
     502    if(rv != 1) { 
     503      return noit_false; 
     504    } 
     505  } 
     506  return noit_true; 
     507} 
    488508int 
    489509noit_check_update(noit_check_t *new_check, 
  • src/noit_check.h

    ra103e78 r7010bc5  
    184184                    int flags); 
    185185 
     186API_EXPORT(noit_boolean) 
     187  noit_check_is_valid_target(const char *str); 
     188 
    186189API_EXPORT(int) 
    187190  noit_check_activate(noit_check_t *check); 
  • src/noit_check_rest.c

    r914f047 r7010bc5  
    236236 
    237237static int 
    238 validate_check_post(xmlDocPtr doc, xmlNodePtr *a, xmlNodePtr *c) { 
     238validate_check_post(xmlDocPtr doc, xmlNodePtr *a, xmlNodePtr *c, 
     239                    const char **error) { 
    239240  xmlNodePtr root, tl, an; 
    240   int name=0, module=0, target=0, period=0, timeout=0, filterset=0, disable=0
     241  int name=0, module=0, target=0, period=0, timeout=0, filterset=0
    241242  *a = *c = NULL; 
    242243  root = xmlDocGetRootElement(doc); 
     
    246247      *a = tl->children; 
    247248      for(an = tl->children; an; an = an->next) { 
    248 #define CHECK_N_SET(a) if(!strcmp((char *)an->name, #a)) a = 1 
    249         CHECK_N_SET(name); 
    250         else CHECK_N_SET(module); 
    251         else CHECK_N_SET(target); 
    252         else CHECK_N_SET(period); 
    253         else CHECK_N_SET(timeout); 
    254         else CHECK_N_SET(filterset); 
    255         else CHECK_N_SET(disable); 
     249#define CHECK_N_SET(a) if(!strcmp((char *)an->name, #a)) 
     250        CHECK_N_SET(name) { 
     251          xmlChar *tmp; 
     252          pcre *valid_name = noit_conf_get_valid_name_checker(); 
     253          int ovector[30], valid; 
     254          tmp = xmlNodeGetContent(an); 
     255          valid = (pcre_exec(valid_name, NULL, 
     256                             (char *)tmp, strlen((char *)tmp), 0, 0, 
     257                             ovector, sizeof(ovector)/sizeof(*ovector)) > 0); 
     258          xmlFree(tmp); 
     259          if(!valid) { *error = "invalid name"; return 0; } 
     260          name = 1; 
     261        } 
     262        else CHECK_N_SET(module) module = 1; /* This is validated by called */ 
     263        else CHECK_N_SET(target) { 
     264          int valid; 
     265          xmlChar *tmp; 
     266          tmp = xmlNodeGetContent(an); 
     267          valid = noit_check_is_valid_target((char *)tmp); 
     268          xmlFree(tmp); 
     269          if(!valid) { *error = "invalid target"; return 0; } 
     270          target = 1; 
     271        } 
     272        else CHECK_N_SET(period) { 
     273          int pint; 
     274          xmlChar *tmp; 
     275          tmp = xmlNodeGetContent(an); 
     276          pint = noit_conf_string_to_int((char *)tmp); 
     277          xmlFree(tmp); 
     278          if(pint < 5000 || pint > 300000) { 
     279            *error = "invalid period"; 
     280            return 0; 
     281          } 
     282          period = 1; 
     283        } 
     284        else CHECK_N_SET(timeout) { 
     285          int pint; 
     286          xmlChar *tmp; 
     287          tmp = xmlNodeGetContent(an); 
     288          pint = noit_conf_string_to_int((char *)tmp); 
     289          xmlFree(tmp); 
     290          if(pint < 0 || pint > 300000) { 
     291            *error = "invalid timeout"; 
     292            return 0; 
     293          } 
     294          timeout = 1; 
     295        } 
     296        else CHECK_N_SET(filterset) filterset = 1; 
     297        else CHECK_N_SET(disable) { /* not required */ 
     298          int valid; 
     299          xmlChar *tmp; 
     300          tmp = xmlNodeGetContent(an); 
     301          valid = (!strcasecmp((char *)tmp, "true") || 
     302                   !strcasecmp((char *)tmp, "on") || 
     303                   !strcasecmp((char *)tmp, "false") || 
     304                   !strcasecmp((char *)tmp, "off")); 
     305          xmlFree(tmp); 
     306          if(!valid) { *error = "bad disable parameter"; return 0; } 
     307          target = 1; 
     308        } 
    256309        else return 0; 
    257310      } 
     
    264317  } 
    265318  if(name && module && target && period && timeout && filterset) return 1; 
     319  *error = "insufficient information"; 
    266320  return 0; 
    267321} 
     
    372426  indoc = xmlParseMemory(rxc->buffer, rxc->len); 
    373427  if(indoc == NULL) FAIL("xml parse error"); 
    374   if(!validate_check_post(indoc, &attr, &config)) FAIL("xml validate error")
     428  if(!validate_check_post(indoc, &attr, &config, &error)) goto error
    375429 
    376430  if(uuid_parse(pats[1], checkid)) goto error; 
  • src/noit_conf.c

    r4fd2f1f r7010bc5  
    152152             err->domain, err->code, err->message); 
    153153} 
     154 
     155 
     156DECLARE_CHECKER(name) 
    154157void noit_conf_init(const char *toplevel) { 
    155158  int i; 
    156159  char keystr[256]; 
     160  COMPILE_CHECKER(name, "^[-_\\.:/a-zA-Z0-9]+$"); 
    157161  xmlSetGenericErrorFunc(noit_error, noit_conf_xml_error_func); 
    158162  xmlSetStructuredErrorFunc(noit_error, noit_conf_xml_error_ext_func); 
     
    423427  return 1; 
    424428} 
     429int noit_conf_string_to_int(const char *str) { 
     430  int base = 10; 
     431  if(!str) return 0; 
     432  if(str[0] == '0') { 
     433    if(str[1] == 'x') base = 16; 
     434    else base = 8; 
     435  } 
     436  return strtol(str, NULL, base); 
     437} 
    425438int noit_conf_get_int(noit_conf_section_t section, 
    426439                      const char *path, int *value) { 
    427440  char *str; 
    428   long longval; 
    429441  if(_noit_conf_get_string(section,NULL,path,&str)) { 
    430     int base = 10; 
    431     if(str[0] == '0') { 
    432       if(str[1] == 'x') base = 16; 
    433       else base = 8; 
    434     } 
    435     longval = strtol(str, NULL, base); 
     442    *value = (int)noit_conf_string_to_int(str); 
    436443    xmlFree(str); 
    437     *value = (int)longval; 
    438444    return 1; 
    439445  } 
     
    446452  return noit_conf_set_string(section,path,buffer); 
    447453} 
     454float noit_conf_string_to_float(const char *str) { 
     455  if(!str) return 0.0; 
     456  return atof(str); 
     457} 
    448458int noit_conf_get_float(noit_conf_section_t section, 
    449459                        const char *path, float *value) { 
    450460  char *str; 
    451461  if(_noit_conf_get_string(section,NULL,path,&str)) { 
    452     *value = atof(str); 
     462    *value = noit_conf_string_to_float(str); 
    453463    xmlFree(str); 
    454464    return 1; 
     
    462472  return noit_conf_set_string(section,path,buffer); 
    463473} 
     474noit_boolean noit_conf_string_to_boolean(const char *str) { 
     475  if(!str) return noit_false; 
     476  if(!strcasecmp(str, "true") || !strcasecmp(str, "on")) return noit_true; 
     477  return noit_false; 
     478} 
    464479int noit_conf_get_boolean(noit_conf_section_t section, 
    465480                          const char *path, noit_boolean *value) { 
    466481  char *str; 
    467482  if(_noit_conf_get_string(section,NULL,path,&str)) { 
    468     if(!strcasecmp(str, "true") || 
    469        !strcasecmp(str, "on")) *value = noit_true; 
    470     else *value = noit_false; 
     483    *value = noit_conf_string_to_boolean(str); 
    471484    xmlFree(str); 
    472485    return 1; 
  • src/noit_conf.h

    r4fd2f1f r7010bc5  
    3939 
    4040#include <uuid/uuid.h> 
     41#include <pcre.h> 
    4142 
    4243typedef void * noit_conf_section_t; 
     
    8182API_EXPORT(int) noit_conf_get_int(noit_conf_section_t section, 
    8283                                  const char *path, int *value); 
     84API_EXPORT(int) noit_conf_string_to_int(const char *str); 
    8385API_EXPORT(int) noit_conf_get_float(noit_conf_section_t section, 
    8486                                    const char *path, float *value); 
     87API_EXPORT(float) noit_conf_string_to_float(const char *str); 
    8588API_EXPORT(int) noit_conf_get_boolean(noit_conf_section_t section, 
    8689                                      const char *path, noit_boolean *value); 
     90API_EXPORT(noit_boolean) noit_conf_string_to_boolean(const char *str); 
     91 
    8792API_EXPORT(int) 
    8893  noit_conf_get_uuid(noit_conf_section_t section, 
     
    119124API_EXPORT(void) noit_conf_log_init(const char *toplevel); 
    120125 
     126#define EXPOSE_CHECKER(name) \ 
     127  API_EXPORT(pcre *) noit_conf_get_valid_##name##_checker(); 
     128#define DECLARE_CHECKER(name) \ 
     129static pcre *checker_valid_##name; \ 
     130pcre *noit_conf_get_valid_##name##_checker() { return checker_valid_##name; } 
     131#define COMPILE_CHECKER(name, expr) do { \ 
     132  const char *errorstr; \ 
     133  int erroff; \ 
     134  checker_valid_##name = pcre_compile(expr, 0, &errorstr, &erroff, NULL); \ 
     135  if(! checker_valid_##name) { \ 
     136    noitL(noit_error, "noit_conf error: compile checker %s failed: %s\n", \ 
     137          #name, errorstr); \ 
     138    exit(-1); \ 
     139  } \ 
     140} while(0) 
     141 
     142EXPOSE_CHECKER(name); 
     143 
    121144#endif