Documentation Source Text

Check-in [5bb4dfcc73]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Update the HTTP server to prohibit malformed and possibly malicious HTTP_HOST parameters.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5bb4dfcc73b900a9f9544333b604dceefba464c9
User & Date: drh 2014-10-05 20:54:57.731
Context
2014-10-05
23:01
Improved documentation comments on the althttpd.c server program. (check-in: d217041b2b user: drh tags: trunk)
20:54
Update the HTTP server to prohibit malformed and possibly malicious HTTP_HOST parameters. (check-in: 5bb4dfcc73 user: drh tags: trunk)
20:07
Move the 3.8.7 release into October. Updates to URI documentation. (check-in: 55869edbde user: drh tags: trunk)
Changes
Side-by-Side Diff Show Whitespace Changes Patch
Changes to misc/althttpd.c.
888
889
890
891
892
893
894








895


























896
897
898
899
900
901
902
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936







+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/* 1x */   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
/* 2x */   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
/* 3x */   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,
/* 4x */   0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
/* 5x */   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,
/* 6x */   0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
/* 7x */   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  1,  0,
/* 8x */   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
/* 9x */   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
/* Ax */   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
/* Bx */   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
/* Cx */   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
/* Dx */   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
/* Ex */   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
/* Fx */   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
};

/*
** Remove all disallowed characters in the input string z[].  Convert any
** disallowed characters into "_".
**
** Not that the three character sequence "%XX" where X is any byte is
** converted into a single "_" character.
**
** Return the number of characters converted.  An "%XX" -> "_" conversion
** counts as a single character.
*/
static int sanitizeString(char *z){
  int nChange = 0;
  while( *z ){
    if( !allowedInName[*(unsigned char*)z] ){
      if( *z=='%' && z[1]!=0 && z[2]!=0 ){
        int i;
        for(i=3; (z[i-2] = z[i])!=0; i++){}
      }
      *z = '_';
      nChange++;
    }
    z++;
  }
  return nChange;
}

/*
** Count the number of "/" characters in a string.
*/
static int countSlashes(const char *z){
  int n = 0;
  while( *z ) if( *(z++)=='/' ) n++;
1015
1016
1017
1018
1019
1020
1021

1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048
1049
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076

1077
1078
1079
1080
1081
1082
1083
1084







+




















-
+







        closeConnection = 1;
      }else if( !forceClose && strcasecmp(zVal, "keep-alive")==0 ){
        closeConnection = 0;
      }
    }else if( strcasecmp(zFieldName,"Host:")==0 ){
      int inSquare = 0;
      char c;
      if( sanitizeString(zVal) ) Forbidden();
      zHttpHost = StrDup(zVal);
      zServerPort = zServerName = StrDup(zHttpHost);
      while( zServerPort && (c = *zServerPort)!=0
              && (c!=':' || inSquare) ){
        if( c=='[' ) inSquare = 1;
        if( c==']' ) inSquare = 0;
        zServerPort++;
      }
      if( zServerPort && *zServerPort ){
        *zServerPort = 0;
        zServerPort++;
      }
      if( zRealPort ){
        zServerPort = StrDup(zRealPort);
      }
    }else if( strcasecmp(zFieldName,"Authorization:")==0 ){
      zAuthType = GetFirstElement(StrDup(zVal), &zAuthArg);
    }
  }

  /* Disallow referring from certain clients */
  /* Disallow requests from certain clients */
  if( zAgent ){
    if( strstr(zAgent, "Windows_9")!=0
     || strstr(zAgent, "Download_Master")!=0
     || strstr(zAgent, "Ezooms/")!=0
   /*|| strstr(zAgent, "bingbot")!=0*/
     || strstr(zAgent, "AhrefsBot")!=0
    ){
1135
1136
1137
1138
1139
1140
1141
1142

1143
1144
1145
1146
1147
1148

1149
1150
1151
1152

1153
1154
1155


1156
1157
1158
1159
1160
1161
1162
1170
1171
1172
1173
1174
1175
1176

1177






1178




1179
1180


1181
1182
1183
1184
1185
1186
1187
1188
1189







-
+
-
-
-
-
-
-
+
-
-
-
-
+

-
-
+
+







  /* Make sure the running time is not too great */
  if( useTimeout ) alarm(10);

  /* Convert all unusual characters in the script name into "_".
  **
  ** This is a defense against various attacks, XSS attacks in particular.
  */
  for(z=zScript; *z; z++){
  sanitizeString(zScript);
    unsigned char c = *(unsigned char*)z;
    if( (c&0x80)!=0 || !allowedInName[c] ){
      *z = '_';
      if( c=='%' && z[1]!=0 && z[2]!=0 ){
        for(i=3; (z[i-2] = z[i])!=0; i++){}
      }

    }
  }

  /* Don't allow "/." or "/-" to to occur anywhere in the entity name.
  /* Do not allow "/." or "/-" to to occur anywhere in the entity name.
  ** This prevents attacks involving ".." and also allows us to create
  ** files and directories whose names begin with "-" which are invisible
  ** to the webserver.
  ** files and directories whose names begin with "-" or "." which are
  ** invisible to the webserver.
  */
  for(z=zScript; *z; z++){
    if( *z=='/' && (z[1]=='.' || z[1]=='-') ){
       NotFound(__LINE__);
    }
  }