pcre_plugin.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /*
  2. 3APA3A simpliest proxy server
  3. (c) 2007-2008 by ZARAZA <3APA3A@security.nnov.ru>
  4. please read License Agreement
  5. */
  6. #include "../../structures.h"
  7. #include <string.h>
  8. #include "pcre.h"
  9. #include "pcreposix.h"
  10. #ifdef __cplusplus
  11. extern "C" {
  12. #endif
  13. #ifndef isnumber
  14. #define isnumber(i_n_arg) ((i_n_arg>='0')&&(i_n_arg<='9'))
  15. #endif
  16. static struct pluginlink * pl;
  17. static pthread_mutex_t pcre_mutex;
  18. static struct filter pcre_first_filter = {
  19. NULL,
  20. "Fake filter",
  21. NULL, NULL,
  22. NULL, NULL,
  23. NULL, NULL, NULL,
  24. NULL, NULL
  25. };
  26. static struct filter *pcre_last_filter;
  27. static int pcre_loaded = 0;
  28. static int pcre_options = 0;
  29. static struct pcreopt {
  30. char * name;
  31. int value;
  32. } pcreopts[]= {
  33. {"PCRE_CASELESS", 0x00000001},
  34. {"PCRE_MULTILINE", 0x00000002},
  35. {"PCRE_DOTALL", 0x00000004},
  36. {"PCRE_EXTENDED", 0x00000008},
  37. {"PCRE_ANCHORED", 0x00000010},
  38. {"PCRE_DOLLAR_ENDONLY", 0x00000020},
  39. {"PCRE_EXTRA", 0x00000040},
  40. {"PCRE_NOTBOL", 0x00000080},
  41. {"PCRE_NOTEOL", 0x00000100},
  42. {"PCRE_UNGREEDY", 0x00000200},
  43. {"PCRE_NOTEMPTY", 0x00000400},
  44. {"PCRE_UTF8", 0x00000800},
  45. {"PCRE_NO_AUTO_CAPTURE", 0x00001000},
  46. {"PCRE_NO_UTF8_CHECK", 0x00002000},
  47. {"PCRE_AUTO_CALLOUT", 0x00004000},
  48. {"PCRE_PARTIAL", 0x00008000},
  49. {"PCRE_DFA_SHORTEST", 0x00010000},
  50. {"PCRE_DFA_RESTART", 0x00020000},
  51. {"PCRE_FIRSTLINE", 0x00040000},
  52. {"PCRE_DUPNAMES", 0x00080000},
  53. {"PCRE_NEWLINE_CR", 0x00100000},
  54. {"PCRE_NEWLINE_LF", 0x00200000},
  55. {"PCRE_NEWLINE_CRLF", 0x00300000},
  56. {"PCRE_NEWLINE_ANY", 0x00400000},
  57. {"PCRE_NEWLINE_ANYCRLF", 0x00500000},
  58. {"PCRE_BSR_ANYCRLF", 0x00800000},
  59. {"PCRE_BSR_UNICODE", 0x01000000},
  60. {NULL, 0}
  61. };
  62. struct pcre_filter_data {
  63. int users;
  64. pcre * re;
  65. int action;
  66. char * replace;
  67. struct ace *acl;
  68. };
  69. static void pcre_data_free(struct pcre_filter_data *pcrefd){
  70. pthread_mutex_lock(&pcre_mutex);
  71. pcrefd->users--;
  72. if(!pcrefd->users){
  73. if(pcrefd->re) pl->myfree(pcrefd->re);
  74. if(pcrefd->acl) pl->freeacl(pcrefd->acl);
  75. if(pcrefd->replace) pl->myfree(pcrefd->replace);
  76. pl->myfree(pcrefd);
  77. }
  78. pthread_mutex_unlock(&pcre_mutex);
  79. }
  80. static void* pcre_filter_open(void * idata, struct srvparam * param){
  81. #define pcrefd ((struct pcre_filter_data *)idata)
  82. if(idata){
  83. pthread_mutex_lock(&pcre_mutex);
  84. pcrefd->users++;
  85. pthread_mutex_unlock(&pcre_mutex);
  86. }
  87. #undef pcrefd
  88. return idata;
  89. }
  90. static FILTER_ACTION pcre_filter_client(void *fo, struct clientparam * param, void** fc){
  91. int res;
  92. struct ace tmpace;
  93. *fc = fo;
  94. if(!fo) return PASS;
  95. #define pcrefd ((struct pcre_filter_data *)fo)
  96. if(!pcrefd->acl) return CONTINUE;
  97. memset (&tmpace, 0, sizeof(struct ace));
  98. tmpace.src = pcrefd->acl->src;
  99. res = pl->ACLMatches(&tmpace, param);
  100. #undef pcrefd
  101. return (res)? CONTINUE:PASS;
  102. }
  103. static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
  104. int ovector[48];
  105. int count = 0;
  106. struct ace *acl;
  107. int match = 0;
  108. int replen, num;
  109. char * replace;
  110. char * tmpbuf, *target, *newbuf;
  111. int nreplaces=0;
  112. #define pcrefd ((struct pcre_filter_data *)fc)
  113. for(acl = pcrefd->acl; acl; acl=acl->next){
  114. if(pl->ACLMatches(pcrefd->acl, param)){
  115. match = 1;
  116. break;
  117. }
  118. }
  119. if(!match) return CONTINUE;
  120. if(!pcrefd->re) return pcrefd->action;
  121. for(; offset < *length_p; nreplaces++){
  122. count = pcre_exec(pcrefd->re, NULL, (char *)*buf_p, *length_p, offset, 0, ovector, 48);
  123. if(count <= 0) break;
  124. if(!(replace = pcrefd->replace) || param->nooverwritefilter) return pcrefd->action;
  125. replen = *length_p - ovector[1];
  126. while(*replace){
  127. if(*replace == '\\' && *(replace +1)){
  128. replace+=2;
  129. ++replen;
  130. }
  131. else if(*replace == '$' && isnumber(*(replace+1))){
  132. replace ++;
  133. num = atoi(replace);
  134. while(isnumber(*replace)) replace++;
  135. if(num > (count - 1)) continue;
  136. replen += (ovector[(num<<1) + 1] - ovector[(num<<1)]);
  137. }
  138. else {
  139. replace++;
  140. replen++;
  141. }
  142. }
  143. tmpbuf = (*pl->myalloc)(replen);
  144. if(!tmpbuf) return CONTINUE;
  145. for(target = tmpbuf, replace = pcrefd->replace; *replace; ){
  146. if(*replace == '\\' && *(replace +1)){
  147. *target++ = replace[1];
  148. replace+=2;
  149. }
  150. else if(*replace == '$' && isnumber(*(replace+1))){
  151. replace ++;
  152. num = atoi(replace);
  153. if(num > (count - 1)) continue;
  154. memcpy(target, *buf_p + ovector[(num<<1)], ovector[(num<<1) + 1] - ovector[(num<<1)]);
  155. target += (ovector[(num<<1) + 1] - ovector[(num<<1)]);
  156. while(isnumber(*replace)) replace++;
  157. }
  158. else {
  159. *target++ = *replace++;
  160. }
  161. }
  162. memcpy(target, *buf_p + ovector[1], *length_p - ovector[1]);
  163. if((ovector[0] + replen + 1) > *bufsize_p){
  164. newbuf = (*pl->myalloc)(ovector[0] + replen + 1);
  165. if(!newbuf){
  166. (*pl->myfree)(tmpbuf);
  167. return CONTINUE;
  168. }
  169. memcpy(newbuf, *buf_p, ovector[0]);
  170. (*pl->myfree)(*buf_p);
  171. *buf_p = (unsigned char *)newbuf;
  172. *bufsize_p = ovector[0] + replen + 1;
  173. }
  174. memcpy(*buf_p + ovector[0], tmpbuf, replen);
  175. (*pl->myfree)(tmpbuf);
  176. (*buf_p)[ovector[0] + replen] = 0;
  177. *length_p = ovector[0] + replen;
  178. if(ovector[0] + replen <= offset){
  179. break;
  180. }
  181. offset = ovector[0] + (int)strlen(pcrefd->replace);
  182. }
  183. return nreplaces? pcrefd->action : CONTINUE;
  184. #undef pcrefd
  185. }
  186. static void pcre_filter_clear(void *fo){
  187. }
  188. static void pcre_filter_close(void *fo){
  189. if(!fo) return;
  190. pcre_data_free((struct pcre_filter_data *)fo);
  191. }
  192. static int h_pcre(int argc, unsigned char **argv){
  193. int action = 0;
  194. pcre *re = NULL;
  195. struct ace *acl;
  196. int offset = 4;
  197. const char * errptr;
  198. struct pcre_filter_data *flt;
  199. struct filter *newf;
  200. char *replace = NULL;
  201. if(!strncmp((char *)argv[2], "allow",5)) action = PASS;
  202. else if(!strncmp((char *)argv[2], "deny",4)) action = REJECT;
  203. else if(!strncmp((char *)argv[2], "remove",6)) action = REMOVE;
  204. else if(!strncmp((char *)argv[2], "dunno",5)) action = CONTINUE;
  205. else return 1;
  206. if(!strncmp((char *)argv[0], "pcre_rewrite", 12)) {
  207. int i,j;
  208. offset = 5;
  209. replace = pl->mystrdup((char *)argv[4]);
  210. if(!replace) return 9;
  211. for(i=0, j=0; replace[i]; i++, j++){
  212. if(replace[i] == '\\'){
  213. switch(replace[i+1]){
  214. case 'r':
  215. i++;
  216. replace[j] = '\r';
  217. break;
  218. case 'n':
  219. i++;
  220. replace[j] = '\n';
  221. break;
  222. case '0':
  223. i++;
  224. replace[j] = 0;
  225. break;
  226. case '\\':
  227. i++;
  228. default:
  229. replace[j] = '\\';
  230. break;
  231. }
  232. }
  233. else replace[j] = replace[i];
  234. }
  235. replace[j] = 0;
  236. }
  237. if(!(acl = pl->make_ace(argc - offset, argv + offset))) return 2;
  238. acl->nolog = (strstr((char *)argv[2],"log") == 0);
  239. if(*argv[3] && !(*argv[3] == '*' && !argv[3][1]) ){
  240. re = pcre_compile((char *)argv[3], pcre_options, &errptr, &offset, NULL);
  241. if(!re) {
  242. pl->myfree(acl);
  243. if(replace) pl->myfree(replace);
  244. return 3;
  245. }
  246. }
  247. flt = pl->myalloc(sizeof(struct pcre_filter_data));
  248. newf = pl->myalloc(sizeof(struct filter));
  249. if(!flt || !newf) {
  250. pl->myfree(acl);
  251. pl->myfree(re);
  252. if(replace) pl->myfree(replace);
  253. if(flt) pl->myfree(flt);
  254. return 4;
  255. }
  256. memset(flt, 0, sizeof(struct pcre_filter_data));
  257. memset(newf, 0, sizeof(struct filter));
  258. flt->action = action;
  259. flt->re = re;
  260. flt->acl = acl;
  261. flt->replace = replace;
  262. flt->users = 1;
  263. newf->instance = "pcre";
  264. newf->data = flt;
  265. newf->filter_open = pcre_filter_open;
  266. newf->filter_client = pcre_filter_client;
  267. if(strstr((char *)argv[1], "request"))newf->filter_request = pcre_filter_buffer;
  268. if(strstr((char *)argv[1], "cliheader"))newf->filter_header_cli = pcre_filter_buffer;
  269. if(strstr((char *)argv[1], "clidata"))newf->filter_data_cli = pcre_filter_buffer;
  270. if(strstr((char *)argv[1], "srvheader"))newf->filter_header_srv = pcre_filter_buffer;
  271. if(strstr((char *)argv[1], "srvdata"))newf->filter_data_srv = pcre_filter_buffer;
  272. newf->filter_clear = pcre_filter_clear;
  273. newf->filter_close = pcre_filter_close;
  274. if(!pcre_last_filter){
  275. newf->next = pcre_first_filter.next;
  276. pcre_first_filter.next=newf;
  277. }
  278. else {
  279. newf->next = pcre_last_filter->next;
  280. pcre_last_filter->next = newf;
  281. }
  282. pcre_last_filter=newf;
  283. return 0;
  284. }
  285. static int h_pcre_extend(int argc, unsigned char **argv){
  286. struct ace *acl;
  287. if(!pcre_last_filter || !pcre_last_filter->data) return 1;
  288. acl = ((struct pcre_filter_data *)pcre_last_filter->data)->acl;
  289. if(!acl) return 2;
  290. for(; acl->next; acl=acl->next);
  291. acl->next = (*pl->make_ace)(argc - 1, argv + 1);
  292. if(!acl->next) return 3;
  293. return 0;
  294. }
  295. static int h_pcre_options(int argc, unsigned char **argv){
  296. int i,j;
  297. pcre_options = 0;
  298. for(j=1; j<argc; j++)
  299. for(i=0; pcreopts[i].name; i++)
  300. if(!strcmp(pcreopts[i].name, (char *)argv[j]))
  301. pcre_options |= pcreopts[i].value;
  302. return 0;
  303. }
  304. static struct commands pcre_commandhandlers[] = {
  305. {pcre_commandhandlers+1, "pcre", h_pcre, 4, 0},
  306. {pcre_commandhandlers+2, "pcre_rewrite", h_pcre, 5, 0},
  307. {pcre_commandhandlers+3, "pcre_extend", h_pcre_extend, 2, 0},
  308. {NULL, "pcre_options", h_pcre_options, 2, 0}
  309. };
  310. static struct symbol regexp_symbols[] = {
  311. {regexp_symbols+1, "regcomp", (void*) regcomp},
  312. {regexp_symbols+2, "regexec", (void*) regexec},
  313. {regexp_symbols+3, "regerror", (void*) regerror},
  314. {regexp_symbols+4, "regfree", (void*) regfree},
  315. {regexp_symbols+5, "pcre_compile", (void*) pcre_compile},
  316. {regexp_symbols+6, "pcre_exec", (void*) pcre_exec},
  317. {NULL, "pcre_free", NULL},
  318. };
  319. #ifdef WATCOM
  320. #pragma aux pcre_plugin "*" parm caller [ ] value struct float struct routine [eax] modify [eax ecx edx]
  321. #undef PLUGINCALL
  322. #define PLUGINCALL
  323. #endif
  324. PLUGINAPI int PLUGINCALL pcre_plugin (struct pluginlink * pluginlink,
  325. int argc, char** argv){
  326. struct filter *flt, *tmpflt;
  327. pl = pluginlink;
  328. pcre_options = 0;
  329. if(!pcre_loaded){
  330. pcre_malloc = pl->myalloc;
  331. pcre_free = pl->myfree;
  332. pcre_loaded = 1;
  333. pthread_mutex_init(&pcre_mutex, NULL);
  334. regexp_symbols[6].value = pl->myfree;
  335. regexp_symbols[6].next = pl->symbols.next;
  336. pl->symbols.next = regexp_symbols;
  337. pcre_commandhandlers[3].next = pl->commandhandlers->next;
  338. pl->commandhandlers->next = pcre_commandhandlers;
  339. pcre_first_filter.next = pl->conf->filters;
  340. pl->conf->filters = &pcre_first_filter;
  341. }
  342. else if(pcre_last_filter){
  343. pcre_first_filter.next = pcre_last_filter->next;
  344. flt = pcre_first_filter.next;
  345. for(; flt; flt = tmpflt){
  346. tmpflt = flt->next;
  347. if(flt->data)
  348. pcre_data_free((struct pcre_filter_data *)flt->data);
  349. pl->myfree(flt);
  350. if(flt == pcre_last_filter) break;
  351. }
  352. }
  353. pcre_last_filter = NULL;
  354. return 0;
  355. }
  356. #ifdef __cplusplus
  357. }
  358. #endif