|
|
1.7 paf 1: /** @file
1.8 paf 2: Parser: String class part: untaint mechanizm.
3:
1.1 paf 4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
1.8 paf 5:
1.1 paf 6: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
7:
1.12 ! paf 8: $Id: untaint.C,v 1.11 2001/03/21 14:06:46 paf Exp $
1.1 paf 9: */
10:
1.12 ! paf 11: #include "pa_config_includes.h"
1.1 paf 12:
13: #include "pa_pool.h"
14: #include "pa_string.h"
15: #include "pa_hash.h"
16: #include "pa_exception.h"
17:
18: #define escape(cases) \
19: { \
20: const char *ptr=row->item.ptr; \
1.3 paf 21: for (int size=row->item.size; size--; ptr++) \
1.1 paf 22: switch(*ptr) { \
23: cases \
24: } \
25: }
1.4 paf 26: #define escape_value(a, c) case a: *copy_here++=c; break
27: #define escape_default default: *copy_here++=*ptr; break
1.1 paf 28: #define escape_subst(a, b, bsize) \
1.4 paf 29: case a: \
1.1 paf 30: strncpy(copy_here, b, bsize); \
31: copy_here+=bsize; \
1.4 paf 32: break
1.9 paf 33: #define escape_encode(need_encode_func, prefix) \
1.5 paf 34: default: \
35: if(need_encode_func(*ptr)) { \
36: static const char *hex="0123456789ABCDEF"; \
1.9 paf 37: char chunk[3]={prefix}; \
1.5 paf 38: chunk[1]=hex[((unsigned char)*ptr)/0x10]; \
39: chunk[2]=hex[((unsigned char)*ptr)%0x10]; \
40: strncpy(copy_here, chunk, 3); copy_here+=3; \
41: } else \
42: *copy_here++=*ptr; \
43: break
1.4 paf 44:
1.9 paf 45: inline bool need_file_encode(unsigned char c){
46: if ((c>='0') && (c<='9') || (c>='A') && (c<='Z') || (c>='a') && (c<='z'))
47: return false;
48:
49: return !strchr("./\\", c);
50: }
1.5 paf 51: inline bool need_uri_encode(unsigned char c){
1.4 paf 52: if ((c>='0') && (c<='9') || (c>='A') && (c<='Z') || (c>='a') && (c<='z'))
53: return false;
54:
1.5 paf 55: return !strchr("_-./", c);
56: }
57: inline bool need_header_encode(unsigned char c){
58: if(strchr(" ,:", c))
59: return false;
60:
61: return need_uri_encode(c);
1.4 paf 62: }
1.1 paf 63:
64: // String
65:
1.9 paf 66: /// @todo optimize whitespaces for all but 'html'
1.1 paf 67: char *String::cstr() const {
1.2 paf 68: char *result=(char *)malloc(size()*UNTAINT_TIMES_BIGGER+1);
1.1 paf 69:
70: char *copy_here=result;
71: const Chunk *chunk=&head;
72: do {
73: const Chunk::Row *row=chunk->rows;
74: for(int i=0; i<chunk->count; i++) {
75: if(row==append_here)
76: goto break2;
77:
78: // WARNING:
79: // string can grow only UNTAINT_TIMES_BIGGER
80: switch(row->item.lang) {
1.11 paf 81: case UL_NO:
1.1 paf 82: // clean piece
1.11 paf 83: case UL_YES:
1.1 paf 84: // tainted piece, but undefined untaint language
85: // for VString.get_double of tainted values
86: // for ^process{body} evaluation
1.11 paf 87: case UL_AS_IS:
1.1 paf 88: // tainted, untaint language: as-is
89: memcpy(copy_here, row->item.ptr, row->item.size);
90: copy_here+=row->item.size;
91: break;
1.11 paf 92: case UL_FILE_NAME:
1.9 paf 93: // tainted, untaint language: file [name]
94: escape(
95: escape_value(' ', '_');
96: escape_encode(need_file_encode, '-');
97: );
98: break;
1.11 paf 99: case UL_URI:
1.4 paf 100: // tainted, untaint language: uri
101: escape(
102: escape_value(' ', '+');
1.9 paf 103: escape_encode(need_uri_encode, '%');
1.5 paf 104: );
105: break;
1.11 paf 106: case UL_HEADER:
1.5 paf 107: // tainted, untaint language: header
108: escape(
1.9 paf 109: escape_encode(need_header_encode, '%');
1.4 paf 110: );
111: break;
1.11 paf 112: case UL_TABLE:
1.1 paf 113: escape(
1.4 paf 114: escape_value('\t', ' ');
115: escape_value('\n', ' ');
116: escape_default;
1.1 paf 117: );
118: break;
1.11 paf 119: case UL_SQL:
1.1 paf 120: // tainted, untaint language: sql
121: // TODO: зависимость от sql сервера
122: memset(copy_here, '?', row->item.size);
123: copy_here+=row->item.size;
124: break;
1.11 paf 125: case UL_JS:
1.1 paf 126: escape(
1.4 paf 127: escape_subst('"', "\\\"", 2);
128: escape_subst('\'', "\\'", 2);
129: escape_subst('\n', "\\n", 2);
130: escape_subst('\r', "\\r", 2);
131: escape_subst('\\', "\\\\", 2);
132: escape_subst('я', "\\я", 2);
133: escape_default;
1.1 paf 134: );
135: break;
1.11 paf 136: case UL_HTML:
1.1 paf 137: escape(
1.4 paf 138: escape_subst('&', "&", 5); // BEFORE consequent relpaces yelding '&'
139: escape_subst('>', ">", 4);
140: escape_subst('<', "<",4);
141: escape_subst('"', """,6);
142: escape_value('\t', ' ');
1.1 paf 143: //TODO: XSLT escape_subst('\'', "'", 6)
1.4 paf 144: escape_default;
1.1 paf 145: );
146: break;
1.11 paf 147: case UL_HTML_TYPO:
1.1 paf 148: // tainted, untaint language: html-typo
149: escape(
1.4 paf 150: escape_subst('&', "&", 5); // BEFORE consequent relpaces yelding '&'
151: escape_subst('>', ">", 4);
152: escape_subst('<', "<",4);
153: escape_subst('"', """,6);
154: escape_value('\t', ' ');
1.1 paf 155: //TODO: $MAIN:html-type table replace, max length(b)==UNTAINT_TIMES_BIGGER*length(a)
1.4 paf 156: escape_default;
1.1 paf 157: );
158: break;
159: default:
160: THROW(0,0,
161: this,
162: "unknown untaint language #%d of %d piece",
163: static_cast<int>(row->item.lang),
164: i);
165: }
166: row++;
167: }
168: chunk=row->link;
169: } while(chunk);
170: break2:
171: *copy_here=0;
172: return result;
173: }