--- parser3/src/main/untaint.C 2001/03/18 16:32:25 1.4 +++ parser3/src/main/untaint.C 2001/03/21 14:06:46 1.11 @@ -1,9 +1,11 @@ -/* - Parser +/** @file + Parser: String class part: untaint mechanizm. + Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) + Author: Alexander Petrosyan (http://design.ru/paf) - $Id: untaint.C,v 1.4 2001/03/18 16:32:25 paf Exp $ + $Id: untaint.C,v 1.11 2001/03/21 14:06:46 paf Exp $ */ #include @@ -28,22 +30,45 @@ strncpy(copy_here, b, bsize); \ copy_here+=bsize; \ break +#define escape_encode(need_encode_func, prefix) \ + default: \ + if(need_encode_func(*ptr)) { \ + static const char *hex="0123456789ABCDEF"; \ + char chunk[3]={prefix}; \ + chunk[1]=hex[((unsigned char)*ptr)/0x10]; \ + chunk[2]=hex[((unsigned char)*ptr)%0x10]; \ + strncpy(copy_here, chunk, 3); copy_here+=3; \ + } else \ + *copy_here++=*ptr; \ + break + +inline bool need_file_encode(unsigned char c){ + if ((c>='0') && (c<='9') || (c>='A') && (c<='Z') || (c>='a') && (c<='z')) + return false; -inline bool need_encode(unsigned char c){ + return !strchr("./\\", c); +} +inline bool need_uri_encode(unsigned char c){ if ((c>='0') && (c<='9') || (c>='A') && (c<='Z') || (c>='a') && (c<='z')) return false; - return strchr("_-./", c)==0; + return !strchr("_-./", c); +} +inline bool need_header_encode(unsigned char c){ + if(strchr(" ,:", c)) + return false; + + return need_uri_encode(c); } // String +/// @todo optimize whitespaces for all but 'html' char *String::cstr() const { char *result=(char *)malloc(size()*UNTAINT_TIMES_BIGGER+1); char *copy_here=result; const Chunk *chunk=&head; - // TODO: оптимизировать whitespaces для всех, кроме 'html' do { const Chunk::Row *row=chunk->rows; for(int i=0; icount; i++) { @@ -53,48 +78,51 @@ char *String::cstr() const { // WARNING: // string can grow only UNTAINT_TIMES_BIGGER switch(row->item.lang) { - case NO: + case UL_NO: // clean piece - case YES: + case UL_YES: // tainted piece, but undefined untaint language // for VString.get_double of tainted values // for ^process{body} evaluation - case AS_IS: + case UL_AS_IS: // tainted, untaint language: as-is memcpy(copy_here, row->item.ptr, row->item.size); copy_here+=row->item.size; break; - case URI: + case UL_FILE_NAME: + // tainted, untaint language: file [name] + escape( + escape_value(' ', '_'); + escape_encode(need_file_encode, '-'); + ); + break; + case UL_URI: // tainted, untaint language: uri escape( escape_value(' ', '+'); - default: - if(need_encode(*ptr)) { - static const char *hex="0123456789ABCDEF"; - char chunk[3]={'%'}; - chunk[1]=hex[((unsigned char)*ptr)/0x10]; - chunk[2]=hex[((unsigned char)*ptr)%0x10]; - strncpy(copy_here, chunk, 3); copy_here+=3; - } else - *copy_here++=*ptr; - - break; + escape_encode(need_uri_encode, '%'); + ); + break; + case UL_HEADER: + // tainted, untaint language: header + escape( + escape_encode(need_header_encode, '%'); ); break; - case TABLE: + case UL_TABLE: escape( escape_value('\t', ' '); escape_value('\n', ' '); escape_default; ); break; - case SQL: + case UL_SQL: // tainted, untaint language: sql // TODO: зависимость от sql сервера memset(copy_here, '?', row->item.size); copy_here+=row->item.size; break; - case JS: + case UL_JS: escape( escape_subst('"', "\\\"", 2); escape_subst('\'', "\\'", 2); @@ -105,7 +133,7 @@ char *String::cstr() const { escape_default; ); break; - case HTML: + case UL_HTML: escape( escape_subst('&', "&", 5); // BEFORE consequent relpaces yelding '&' escape_subst('>', ">", 4); @@ -116,7 +144,7 @@ char *String::cstr() const { escape_default; ); break; - case HTML_TYPO: + case UL_HTML_TYPO: // tainted, untaint language: html-typo escape( escape_subst('&', "&", 5); // BEFORE consequent relpaces yelding '&'