00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <ctype.h>
00020 #include <sys/types.h>
00021
00022 #include "hi_client_norm.h"
00023 #include "hi_eo.h"
00024 #include "hi_eo_events.h"
00025 #include "hi_eo_log.h"
00026 #include "hi_ui_iis_unicode_map.h"
00027 #include "hi_return_codes.h"
00028 #include "hi_si.h"
00029 #include "hi_util.h"
00030 #include "hi_util_xmalloc.h"
00031
00032 #define MAX_DIRS 2048
00033
00034 #define NO_HEX_VAL -1
00035 #define BASE36_VAL -2
00036 #define HEX_VAL 1
00037
00038
00039
00040
00041
00042
00043 #define GET_ERR 0x80000000
00044 #define END_OF_BUFFER -1
00045 #define DOUBLE_ENCODING -2
00046 #define DIR_TRAV -2
00047
00048 #define NON_ASCII_CHAR 0xff
00049
00050 typedef struct s_URI_NORM_STATE
00051 {
00052 u_char *abs_uri;
00053 u_char *param;
00054
00055
00056
00057
00058 u_char *dir_track[MAX_DIRS];
00059 u_int dir_count;
00060
00061 } URI_NORM_STATE;
00062
00063 typedef int (*DECODE_FUNC)(HI_SESSION *, u_char *,
00064 u_char *, u_char **, URI_NORM_STATE *);
00065
00066 static int hex_lookup[256];
00067 static int valid_lookup[256];
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 static int GetPtr(HI_SESSION *Session, u_char *start,
00101 u_char *end, u_char **ptr, URI_NORM_STATE *norm_state)
00102 {
00103 HTTPINSPECT_CONF *ServerConf = Session->server_conf;
00104
00105 (*ptr)++;
00106
00107 if(!hi_util_in_bounds(start, end, *ptr))
00108 return END_OF_BUFFER;
00109
00110 if(ServerConf->double_decoding.on && **ptr == '%')
00111 return DOUBLE_ENCODING;
00112
00113 return (int)**ptr;
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 static int UDecode(HI_SESSION *Session, u_char *start,
00151 u_char *end, u_char **ptr, DECODE_FUNC get_byte,
00152 URI_NORM_STATE *norm_state)
00153 {
00154 HTTPINSPECT_CONF *ServerConf = Session->server_conf;
00155 int iByte;
00156 int iNorm;
00157 int iCtr;
00158
00159 iNorm = 0;
00160
00161 for(iCtr = 0; iCtr < 4; iCtr++)
00162 {
00163 iByte = get_byte(Session, start, end, ptr, norm_state);
00164 if(iByte & GET_ERR)
00165 return iByte;
00166
00167 if(valid_lookup[(u_char)iByte] < 0)
00168 return NON_ASCII_CHAR;
00169
00170 iNorm <<= 4;
00171 iNorm = (iNorm | (hex_lookup[(u_char)iByte]));
00172 }
00173
00174
00175
00176
00177
00178 if(iNorm > 0xff)
00179 {
00180
00181
00182
00183 if(ServerConf->iis_unicode.on && iNorm <= 0xffff)
00184 {
00185 iNorm = ServerConf->iis_unicode_map[iNorm];
00186
00187 if(iNorm == HI_UI_NON_ASCII_CODEPOINT)
00188 {
00189 iNorm = NON_ASCII_CHAR;
00190 }
00191
00192 if(hi_eo_generate_event(Session, ServerConf->iis_unicode.alert) &&
00193 !norm_state->param)
00194 {
00195 hi_eo_client_event_log(Session, HI_EO_CLIENT_IIS_UNICODE,
00196 NULL, NULL);
00197 }
00198 }
00199 else
00200 {
00201 return NON_ASCII_CHAR;
00202 }
00203 }
00204
00205
00206
00207
00208 if(hi_eo_generate_event(Session, ServerConf->u_encoding.alert) &&
00209 !norm_state->param)
00210 {
00211 hi_eo_client_event_log(Session, HI_EO_CLIENT_U_ENCODE,
00212 NULL, NULL);
00213 }
00214
00215 return iNorm;
00216 }
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 static int PercentDecode(HI_SESSION *Session, u_char *start,
00254 u_char *end, u_char **ptr, URI_NORM_STATE *norm_state)
00255 {
00256 HTTPINSPECT_CONF *ServerConf = Session->server_conf;
00257 int iByte;
00258 u_char *orig_ptr;
00259 int iNorm;
00260
00261 orig_ptr = *ptr;
00262
00263 iByte = GetPtr(Session, start, end, ptr, norm_state);
00264 if(iByte & GET_ERR)
00265 {
00266 if(iByte == END_OF_BUFFER)
00267 return END_OF_BUFFER;
00268
00269 if(iByte == DOUBLE_ENCODING)
00270 {
00271 *ptr = orig_ptr;
00272 return (int)**ptr;
00273 }
00274 }
00275
00276
00277
00278
00279 iNorm = 0;
00280
00281
00282
00283
00284 if(valid_lookup[(u_char)iByte] < 0)
00285 {
00286
00287
00288
00289
00290
00291 if(ServerConf->u_encoding.on && (toupper(iByte) == 'U'))
00292 {
00293 iNorm = UDecode(Session, start, end, ptr, GetPtr, norm_state);
00294
00295
00296
00297
00298
00299 if(iNorm & GET_ERR)
00300 {
00301 if(iNorm == END_OF_BUFFER)
00302 {
00303
00304
00305
00306
00307 return END_OF_BUFFER;
00308 }
00309
00310 if(iNorm == DOUBLE_ENCODING)
00311 {
00312 *ptr = orig_ptr;
00313 return (int)**ptr;
00314 }
00315 }
00316
00317 return iNorm;
00318 }
00319 else if(!ServerConf->base36.on ||
00320 valid_lookup[(u_char)iByte] != BASE36_VAL)
00321 {
00322 return NON_ASCII_CHAR;
00323 }
00324
00325
00326
00327
00328
00329 if(hi_eo_generate_event(Session, ServerConf->base36.alert) &&
00330 !norm_state->param)
00331 {
00332 hi_eo_client_event_log(Session, HI_EO_CLIENT_BASE36, NULL, NULL);
00333 }
00334 }
00335
00336 iNorm = (hex_lookup[(u_char)iByte]<<4);
00337 iByte = GetPtr(Session, start, end, ptr, norm_state);
00338 if(iByte & GET_ERR)
00339 {
00340 if(iByte == END_OF_BUFFER)
00341 return END_OF_BUFFER;
00342
00343 if(iByte == DOUBLE_ENCODING)
00344 {
00345 *ptr = orig_ptr;
00346 return (int)**ptr;
00347 }
00348 }
00349
00350 if(valid_lookup[(u_char)iByte] < 0)
00351 {
00352 if(!ServerConf->base36.on || valid_lookup[(u_char)iByte] != BASE36_VAL)
00353 {
00354 return NON_ASCII_CHAR;
00355 }
00356
00357
00358
00359
00360
00361 if(hi_eo_generate_event(Session, ServerConf->base36.alert) &&
00362 !norm_state->param)
00363 {
00364 hi_eo_client_event_log(Session, HI_EO_CLIENT_BASE36, NULL, NULL);
00365 }
00366 }
00367
00368 iNorm = (iNorm | (hex_lookup[(u_char)iByte])) & 0xff;
00369
00370 if(hi_eo_generate_event(Session,ServerConf->ascii.alert) &&
00371 !norm_state->param)
00372 {
00373 hi_eo_client_event_log(Session, HI_EO_CLIENT_ASCII,
00374 NULL, NULL);
00375 }
00376
00377 return iNorm;
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 static int GetChar(HI_SESSION *Session, u_char *start,
00408 u_char *end, u_char **ptr, int *bare_byte,
00409 URI_NORM_STATE *norm_state)
00410 {
00411 HTTPINSPECT_CONF *ServerConf = Session->server_conf;
00412 int iNorm;
00413
00414 if(!hi_util_in_bounds(start, end, *ptr))
00415 return END_OF_BUFFER;
00416
00417 iNorm = (int)(**ptr);
00418
00419 if(**ptr == '%' && ServerConf->ascii.on)
00420 {
00421
00422
00423
00424 iNorm = PercentDecode(Session, start, end, ptr, norm_state);
00425
00426
00427
00428
00429
00430
00431 if(iNorm == END_OF_BUFFER)
00432 return NON_ASCII_CHAR;
00433
00434 *bare_byte = 0;
00435 }
00436 else
00437 {
00438 if(ServerConf->bare_byte.on && (u_char)iNorm > 0x7f)
00439 {
00440 if(hi_eo_generate_event(Session, ServerConf->bare_byte.alert) &&
00441 !norm_state->param)
00442 {
00443 hi_eo_client_event_log(Session, HI_EO_CLIENT_BARE_BYTE,
00444 NULL, NULL);
00445 }
00446
00447
00448
00449
00450 *bare_byte = 0;
00451 }
00452 else
00453 {
00454
00455
00456
00457 *bare_byte = 1;
00458 }
00459 }
00460
00461
00462
00463
00464 (*ptr)++;
00465
00466 return iNorm;
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 static int UTF8Decode(HI_SESSION *Session, u_char *start,
00498 u_char *end, u_char **ptr, int iFirst,
00499 URI_NORM_STATE *norm_state)
00500 {
00501 HTTPINSPECT_CONF *ServerConf = Session->server_conf;
00502 int iBareByte;
00503 int iNorm;
00504 int iNumBytes;
00505 int iCtr;
00506 int iByte;
00507
00508
00509
00510
00511
00512 if((iFirst & 0xe0) == 0xc0)
00513 {
00514 iNumBytes = 1;
00515 iNorm = iFirst & 0x1f;
00516 }
00517 else if((iFirst & 0xf0) == 0xe0)
00518 {
00519 iNumBytes = 2;
00520 iNorm = iFirst & 0x0f;
00521 }
00522 else
00523 {
00524
00525
00526
00527
00528 return iFirst;
00529 }
00530
00531
00532
00533
00534
00535
00536
00537 for(iCtr = 0; iCtr < iNumBytes; iCtr++)
00538 {
00539 iByte = GetChar(Session, start, end, ptr, &iBareByte, norm_state);
00540 if(iByte == END_OF_BUFFER || iBareByte)
00541 return NON_ASCII_CHAR;
00542
00543 if((iByte & 0xc0) == 0x80)
00544 {
00545 iNorm <<= 6;
00546 iNorm |= (iByte & 0x3f);
00547 }
00548 else
00549 {
00550
00551
00552
00553
00554 return NON_ASCII_CHAR;
00555 }
00556 }
00557
00558
00559
00560
00561
00562 if(iNorm > 0x7f)
00563 {
00564 if(ServerConf->iis_unicode.on)
00565 {
00566 iNorm = ServerConf->iis_unicode_map[iNorm];
00567
00568 if(iNorm == HI_UI_NON_ASCII_CODEPOINT)
00569 {
00570 iNorm = NON_ASCII_CHAR;
00571 }
00572
00573 if(hi_eo_generate_event(Session, ServerConf->iis_unicode.alert) &&
00574 !norm_state->param)
00575 {
00576 hi_eo_client_event_log(Session, HI_EO_CLIENT_IIS_UNICODE,
00577 NULL, NULL);
00578 }
00579
00580 return iNorm;
00581 }
00582 else
00583 {
00584 iNorm = NON_ASCII_CHAR;
00585 }
00586 }
00587
00588 if(hi_eo_generate_event(Session, ServerConf->utf_8.alert) &&
00589 !norm_state->param)
00590 {
00591 hi_eo_client_event_log(Session, HI_EO_CLIENT_UTF_8,
00592 NULL, NULL);
00593 }
00594
00595 return iNorm;
00596 }
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618 static int UnicodeDecode(HI_SESSION *Session, u_char *start,
00619 u_char *end, u_char **ptr, int iFirst,
00620 URI_NORM_STATE *norm_state)
00621 {
00622 HTTPINSPECT_CONF *ServerConf = Session->server_conf;
00623 int iNorm = iFirst;
00624
00625 if(ServerConf->iis_unicode.on || ServerConf->utf_8.on)
00626 {
00627 iNorm = UTF8Decode(Session, start, end, ptr, iFirst, norm_state);
00628 }
00629
00630 return iNorm;
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655 static int GetByte(HI_SESSION *Session, u_char *start, u_char *end,
00656 u_char **ptr, URI_NORM_STATE *norm_state)
00657 {
00658 int iChar;
00659 int iBareByte;
00660
00661 iChar = GetChar(Session, start, end, ptr, &iBareByte, norm_state);
00662 if(iChar == END_OF_BUFFER)
00663 return END_OF_BUFFER;
00664
00665
00666
00667
00668 if((iChar & 0x80) && (iChar != NON_ASCII_CHAR) && !iBareByte)
00669 {
00670 iChar = UnicodeDecode(Session, start, end, ptr, iChar, norm_state);
00671 }
00672
00673 return iChar;
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 static int DoubleDecode(HI_SESSION *Session, u_char *start,
00707 u_char *end, u_char **ptr,
00708 URI_NORM_STATE *norm_state)
00709 {
00710 HTTPINSPECT_CONF *ServerConf = Session->server_conf;
00711 int iByte;
00712 int iNorm;
00713 u_char *orig_ptr;
00714
00715 orig_ptr = *ptr;
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 iByte = GetByte(Session, start, end, ptr, norm_state);
00733 if(iByte == END_OF_BUFFER)
00734 return NON_ASCII_CHAR;
00735
00736 if(valid_lookup[(u_char)iByte] < 0)
00737 {
00738 if(ServerConf->u_encoding.on && (toupper(iByte) == 'U'))
00739 {
00740 iNorm = UDecode(Session, start, end, ptr, GetByte, norm_state);
00741
00742 if(iNorm == END_OF_BUFFER)
00743 {
00744
00745
00746
00747
00748
00749
00750 return NON_ASCII_CHAR;
00751 }
00752
00753 return iNorm;
00754 }
00755
00756 return iByte;
00757 }
00758
00759 iNorm = (hex_lookup[(u_char)iByte]<<4);
00760
00761 iByte = GetByte(Session, start, end, ptr, norm_state);
00762 if(iByte == END_OF_BUFFER)
00763 return NON_ASCII_CHAR;
00764
00765 if(valid_lookup[(u_char)iByte] < 0)
00766 {
00767 return iByte;
00768 }
00769
00770 iNorm = (iNorm | (hex_lookup[(u_char)iByte])) & 0xff;
00771
00772 if(hi_eo_generate_event(Session, ServerConf->double_decoding.alert) &&
00773 (norm_state->param == NULL))
00774 {
00775 hi_eo_client_event_log(Session, HI_EO_CLIENT_DOUBLE_DECODE,
00776 NULL, NULL);
00777 }
00778
00779 return iNorm;
00780 }
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814 static int GetDecodedByte(HI_SESSION *Session, u_char *start,
00815 u_char *end, u_char **ptr,
00816 URI_NORM_STATE *norm_state)
00817 {
00818 HTTPINSPECT_CONF *ServerConf = Session->server_conf;
00819 int iChar;
00820
00821 iChar = GetByte(Session,start,end,ptr, norm_state);
00822 if(iChar == END_OF_BUFFER)
00823 return END_OF_BUFFER;
00824
00825 if(ServerConf->double_decoding.on && (u_char)iChar == '%')
00826 {
00827 iChar = DoubleDecode(Session,start,end,ptr, norm_state);
00828 }
00829
00830
00831
00832
00833 if(ServerConf->iis_backslash.on && (u_char)iChar == 0x5c)
00834 {
00835 if(hi_eo_generate_event(Session, ServerConf->iis_backslash.alert) &&
00836 !norm_state->param)
00837 {
00838 hi_eo_client_event_log(Session, HI_EO_CLIENT_IIS_BACKSLASH,
00839 NULL, NULL);
00840 }
00841
00842 iChar = 0x2f;
00843 }
00844
00845 return iChar;
00846 }
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 static int DirTrav(HI_SESSION *Session, URI_NORM_STATE *norm_state,
00869 u_char *ub_start,u_char **ub_ptr)
00870 {
00871 HTTPINSPECT_CONF *ServerConf = Session->server_conf;
00872
00873 if(norm_state->dir_count)
00874 {
00875 *ub_ptr = norm_state->dir_track[norm_state->dir_count - 1];
00876
00877
00878
00879
00880 if(norm_state->dir_count >= 1)
00881 {
00882 norm_state->dir_count--;
00883 }
00884 }
00885 else
00886 {
00887
00888
00889
00890
00891
00892
00893 *ub_ptr = ub_start;
00894
00895
00896
00897
00898 if(hi_eo_generate_event(Session, ServerConf->webroot.alert) &&
00899 !norm_state->param)
00900 {
00901 hi_eo_client_event_log(Session, HI_EO_CLIENT_WEBROOT_DIR,
00902 NULL, NULL);
00903 }
00904 }
00905
00906 return HI_SUCCESS;
00907 }
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930 static int DirSet(URI_NORM_STATE *norm_state, u_char **ub_ptr)
00931 {
00932
00933
00934
00935
00936 **ub_ptr = '/';
00937
00938 if(!norm_state->param)
00939 {
00940 norm_state->dir_track[norm_state->dir_count] = *ub_ptr;
00941 if(norm_state->dir_count < MAX_DIRS)
00942 norm_state->dir_count++;
00943 }
00944
00945 (*ub_ptr)++;
00946
00947 return HI_SUCCESS;
00948 }
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996 static int DirNorm(HI_SESSION *Session, u_char *start, u_char *end,
00997 u_char **ptr, URI_NORM_STATE *norm_state)
00998 {
00999 HTTPINSPECT_CONF *ServerConf = Session->server_conf;
01000 int iChar;
01001 int iDir;
01002 u_char *orig_ptr;
01003 u_char *dir_ptr;
01004
01005 while((iChar = GetDecodedByte(Session, start, end, ptr, norm_state)) !=
01006 END_OF_BUFFER)
01007 {
01008 orig_ptr = *ptr;
01009
01010
01011
01012
01013
01014
01015
01016 if((u_char)iChar < 0x30)
01017 {
01018
01019
01020
01021
01022 if(ServerConf->multiple_slash.on && (u_char)iChar == '/')
01023 {
01024 if(hi_eo_generate_event(Session,
01025 ServerConf->multiple_slash.alert) &&
01026 !norm_state->param)
01027 {
01028 hi_eo_client_event_log(Session,
01029 HI_EO_CLIENT_MULTI_SLASH,
01030 NULL, NULL);
01031 }
01032
01033 continue;
01034 }
01035
01036
01037
01038
01039 else if(ServerConf->directory.on && (u_char)iChar == '.' &&
01040 !norm_state->param)
01041 {
01042 iDir = GetDecodedByte(Session,start,end,ptr,norm_state);
01043 if(iDir != END_OF_BUFFER)
01044 {
01045 if((u_char)iDir == '.')
01046 {
01047
01048
01049
01050
01051
01052
01053 dir_ptr = *ptr;
01054
01055 iDir = GetDecodedByte(Session,start,end,ptr,norm_state);
01056 if(iDir != END_OF_BUFFER)
01057 {
01058 if((u_char)iDir == '/')
01059 {
01060
01061
01062
01063
01064
01065 if(hi_eo_generate_event(Session,
01066 ServerConf->directory.alert)&&
01067 !norm_state->param)
01068 {
01069 hi_eo_client_event_log(Session,
01070 HI_EO_CLIENT_DIR_TRAV,
01071 NULL, NULL);
01072 }
01073
01074 *ptr = dir_ptr;
01075 return DIR_TRAV;
01076 }
01077 }
01078
01079 *ptr = orig_ptr;
01080 return iChar;
01081 }
01082 else if((u_char)iDir == '/')
01083 {
01084
01085
01086
01087
01088
01089
01090 if(hi_eo_generate_event(Session,
01091 ServerConf->directory.alert) &&
01092 !norm_state->param)
01093 {
01094 hi_eo_client_event_log(Session,
01095 HI_EO_CLIENT_SELF_DIR_TRAV,
01096 NULL, NULL);
01097 }
01098
01099 continue;
01100 }
01101 }
01102
01103
01104
01105
01106
01107 *ptr = orig_ptr;
01108 return iChar;
01109 }
01110 }
01111
01112
01113
01114
01115 return iChar;
01116 }
01117
01118 return END_OF_BUFFER;
01119 }
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136 static int CheckLongDir(HI_SESSION *Session, URI_NORM_STATE *norm_state,
01137 u_char *ub_ptr)
01138 {
01139 int iDirLen;
01140 u_char *LastDir;
01141
01142
01143
01144
01145
01146 if(Session->server_conf->long_dir && norm_state->dir_count &&
01147 !norm_state->param)
01148 {
01149 LastDir = norm_state->dir_track[norm_state->dir_count - 1];
01150
01151 iDirLen = ub_ptr - LastDir;
01152
01153 if(iDirLen > Session->server_conf->long_dir &&
01154 hi_eo_generate_event(Session, HI_EO_CLIENT_OVERSIZE_DIR) &&
01155 !norm_state->param)
01156 {
01157 hi_eo_client_event_log(Session, HI_EO_CLIENT_OVERSIZE_DIR,
01158 NULL, NULL);
01159 }
01160 }
01161
01162 return HI_SUCCESS;
01163 }
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202 static INLINE int InspectUriChar(HI_SESSION *Session, int iChar,
01203 URI_NORM_STATE *norm_state,
01204 u_char *start, u_char *end, u_char **ptr,
01205 u_char *ub_start, u_char *ub_end,
01206 u_char **ub_ptr)
01207 {
01208 HTTPINSPECT_CONF *ServerConf = Session->server_conf;
01209 int iDir;
01210
01211
01212
01213
01214 if(!norm_state->dir_count && (u_char)iChar == ':' &&
01215 hi_util_in_bounds(start, end, ((*ptr)+2)))
01216 {
01217 if(**ptr == '/' && *((*ptr)+1) == '/')
01218 {
01219
01220
01221
01222 if(!hi_util_in_bounds(ub_start, ub_end, ((*ub_ptr)+2)))
01223 return END_OF_BUFFER;
01224
01225
01226
01227
01228 **ub_ptr = (u_char)iChar;
01229 (*ub_ptr)++;
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248 (*ptr)++;
01249
01250 return HI_SUCCESS;
01251 }
01252 }
01253
01254
01255
01256
01257
01258
01259
01260 if((u_char)iChar == '/')
01261 {
01262
01263
01264
01265 CheckLongDir(Session, norm_state, *ub_ptr);
01266
01267 iDir = DirNorm(Session, start, end, ptr, norm_state);
01268
01269 if(iDir == DIR_TRAV)
01270 {
01271
01272
01273
01274
01275
01276
01277
01278
01279 DirTrav(Session,norm_state, ub_start, ub_ptr);
01280 }
01281 else
01282 {
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292 DirSet(norm_state, ub_ptr);
01293 if(iDir == END_OF_BUFFER)
01294 return END_OF_BUFFER;
01295
01296
01297
01298
01299 if(!hi_util_in_bounds(ub_start, ub_end, *ub_ptr))
01300 return END_OF_BUFFER;
01301
01302
01303
01304
01305
01306
01307
01308
01309 if(ServerConf->non_rfc_chars[(u_char)iDir])
01310 {
01311 if(hi_eo_generate_event(Session, HI_EO_CLIENT_NON_RFC_CHAR) &&
01312 !norm_state->param)
01313 {
01314 hi_eo_client_event_log(Session, HI_EO_CLIENT_NON_RFC_CHAR,
01315 NULL, NULL);
01316 }
01317 }
01318
01319 **ub_ptr = (u_char)iDir;
01320 (*ub_ptr)++;
01321 }
01322
01323 return HI_SUCCESS;
01324 }
01325
01326 if((u_char)iChar == '?')
01327 {
01328
01329
01330
01331
01332
01333
01334 CheckLongDir(Session, norm_state, *ub_ptr);
01335 norm_state->param = *ub_ptr;
01336 }
01337
01338
01339
01340
01341
01342 return HI_NONFATAL_ERR;
01343 }
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376 int hi_norm_uri(HI_SESSION *Session, u_char *uribuf, int *uribuf_size,
01377 u_char *uri, int uri_size)
01378 {
01379 HTTPINSPECT_CONF *ServerConf;
01380 int iChar;
01381 int iRet;
01382 int iMaxUriBufSize;
01383 URI_NORM_STATE norm_state;
01384 u_char *ub_ptr;
01385 u_char *ptr;
01386 u_char *start;
01387 u_char *end;
01388 u_char *ub_start;
01389 u_char *ub_end;
01390
01391 ServerConf = Session->server_conf;
01392
01393 iMaxUriBufSize = *uribuf_size;
01394
01395 start = uri;
01396 end = uri + uri_size;
01397 ub_start = uribuf;
01398 ub_end = uribuf + iMaxUriBufSize;
01399
01400 ub_ptr = uribuf;
01401 ptr = uri;
01402
01403
01404
01405
01406 norm_state.dir_count = 0;
01407 norm_state.param = NULL;
01408
01409 while(hi_util_in_bounds(ub_start, ub_end, ub_ptr))
01410 {
01411
01412 iChar = GetDecodedByte(Session, start, end, &ptr, &norm_state);
01413 if(iChar == END_OF_BUFFER)
01414 break;
01415
01416
01417
01418
01419
01420 if(ServerConf->non_rfc_chars[(u_char)iChar])
01421 {
01422 if(hi_eo_generate_event(Session, HI_EO_CLIENT_NON_RFC_CHAR) &&
01423 !norm_state.param)
01424 {
01425 hi_eo_client_event_log(Session, HI_EO_CLIENT_NON_RFC_CHAR,
01426 NULL, NULL);
01427 }
01428 }
01429
01430 if((iRet=InspectUriChar(Session, iChar, &norm_state, start, end, &ptr,
01431 ub_start, ub_end, &ub_ptr)))
01432 {
01433 if(iRet == END_OF_BUFFER)
01434 break;
01435
01436
01437
01438
01439
01440 *ub_ptr = (u_char)iChar;
01441 ub_ptr++;
01442 }
01443 }
01444
01445
01446
01447
01448
01449 CheckLongDir(Session, &norm_state, ub_ptr);
01450
01451
01452
01453
01454
01455 *uribuf_size = ub_ptr - ub_start;
01456
01457 if(*uribuf_size > uri_size || *uribuf_size < 1)
01458 return HI_NONFATAL_ERR;
01459
01460 return HI_SUCCESS;
01461 }
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477 int hi_norm_init(HTTPINSPECT_GLOBAL_CONF *GlobalConf)
01478 {
01479 int iCtr;
01480 int iNum;
01481
01482 memset(hex_lookup, NO_HEX_VAL, sizeof(hex_lookup));
01483 memset(valid_lookup, NO_HEX_VAL, sizeof(valid_lookup));
01484
01485
01486
01487
01488 iNum = 0;
01489 for(iCtr = 48; iCtr < 58; iCtr++)
01490 {
01491 hex_lookup[iCtr] = iNum;
01492 valid_lookup[iCtr] = HEX_VAL;
01493 iNum++;
01494 }
01495
01496
01497
01498
01499 iNum = 10;
01500 for(iCtr = 65; iCtr < 71; iCtr++)
01501 {
01502 hex_lookup[iCtr] = iNum;
01503 valid_lookup[iCtr] = HEX_VAL;
01504 iNum++;
01505 }
01506
01507 iNum = 16;
01508 for(iCtr = 71; iCtr < 91; iCtr++)
01509 {
01510 hex_lookup[iCtr] = iNum;
01511 valid_lookup[iCtr] = BASE36_VAL;
01512 iNum++;
01513 }
01514
01515
01516
01517
01518 iNum = 10;
01519 for(iCtr = 97; iCtr < 103; iCtr++)
01520 {
01521 hex_lookup[iCtr] = iNum;
01522 valid_lookup[iCtr] = HEX_VAL;
01523 iNum++;
01524 }
01525
01526 iNum = 16;
01527 for(iCtr = 103; iCtr < 123; iCtr++)
01528 {
01529 hex_lookup[iCtr] = iNum;
01530 valid_lookup[iCtr] = BASE36_VAL;
01531 iNum++;
01532 }
01533
01534 return HI_SUCCESS;
01535 }
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555 int hi_normalization(HI_SESSION *Session, int iInspectMode)
01556 {
01557 int iRet;
01558
01559 if(!Session)
01560 {
01561 return HI_INVALID_ARG;
01562 }
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572 if(iInspectMode == HI_SI_CLIENT_MODE)
01573 {
01574 if((iRet = hi_client_norm((void *)Session)))
01575 {
01576 return iRet;
01577 }
01578 }
01579
01580 return HI_SUCCESS;
01581 }