1 #include <string.h>
   2 #include <stdio.h>
   3 #include <errno.h>
   4 #include "rh_string.h"
   5 #include "rhttpd.h"
   6 #include "http.h"
   7 #include "http_header.h"
   8 #include "http_host.h"
   9 #include "rh_chunk.h"
  10 #include "http_range.h"
  11 #include "log.h"
  12 
  13 #define MAP_WANT_HTTP_HOST      MAP_HTTP_HOST
  14 #define MAP_WANT_HTTP_KEY       MAP_HTTP_KEY
  15 #define MAP_WANT_HTTP_VAL       MAP_HTTP_VAL
  16 #include "rh_charmap.h"
  17 
  18 #define DECLARE_PROTO(_call,_name)                                      \
  19         static http_status_t http_header_ ## _call ## _ ## _name        \
  20                 (http_header_entry_t *entry)
  21 
  22 DECLARE_PROTO(parse,    host);
  23 DECLARE_PROTO(destroy,  host);
  24 DECLARE_PROTO(parse,    validate);
  25 DECLARE_PROTO(parse,    connection);
  26 
  27 #undef DECLARE_PROTO
  28 
  29 
  30 #define http_header_parse_NULL          NULL
  31 #define http_header_destroy_NULL        NULL
  32 
  33 #define DECLARE_KEY(_key, _merge_ch, _type,_first,_full,_destroy)       \
  34         {       CONST_STR_LEN(_key),                                    \
  35                 _merge_ch,                                              \
  36                 HTTP_HEADER_KEY_ ## _type,                              \
  37                 http_header_parse_ ## _first,                           \
  38                 http_header_parse_ ## _full,                            \
  39                 http_header_destroy_ ## _destroy                        \
  40         }
  41 
  42 static const struct http_header_key
  43 http_header_keys[HTTP_HEADER_KEY_MAX] =
  44 {
  45         DECLARE_KEY("", ' ', RESPONSE, NULL, NULL, NULL),
  46         
  47         DECLARE_KEY("Host", ' ', HOST, host, NULL, host),
  48         DECLARE_KEY("ETag", ' ', ETAG, validate, NULL, NULL),
  49         DECLARE_KEY("Date", ' ', DATE, validate, NULL, NULL),
  50         DECLARE_KEY("From", ' ', FROM, validate, NULL, NULL),
  51         DECLARE_KEY("Vary", ' ', VARY, validate, NULL, NULL),
  52         
  53         DECLARE_KEY("TE", ' ', TE, validate, NULL, NULL),
  54         
  55         DECLARE_KEY("Via", ' ', VIA, validate, NULL, NULL),
  56         DECLARE_KEY("Age", ' ', AGE, validate, NULL, NULL),
  57         
  58         DECLARE_KEY("Title", ' ', TITLE, validate, NULL, NULL),
  59         DECLARE_KEY("Range", ' ', RANGE, range, NULL, range),
  60         DECLARE_KEY("X-Pad", ' ', X_PAD, validate, NULL, NULL),
  61         DECLARE_KEY("Allow", ' ', ALLOW, validate, NULL, NULL),
  62         DECLARE_KEY("UA-OS", ' ', UA_OS, validate, NULL, NULL),
  63 
  64         DECLARE_KEY("Set-Cookie", ' ', SET_COOKIE, validate, NULL, NULL),
  65         DECLARE_KEY("Connection", ' ', CONNECTION, connection, NULL, NULL),
  66         DECLARE_KEY("User-Agent", ' ', USER_AGENT, validate, NULL, NULL),
  67         DECLARE_KEY("Keep-Alive", ' ', KEEP_ALIVE, validate, NULL, NULL),
  68         
  69         DECLARE_KEY("Accept", ' ', ACCEPT, validate, NULL, NULL),
  70         DECLARE_KEY("Cookie", ' ', COOKIE, validate, NULL, NULL),
  71         DECLARE_KEY("UA-CPU", ' ', UA_CPU, validate, NULL, NULL),
  72         DECLARE_KEY("Expect", ' ', EXPECT, validate, NULL, NULL),
  73         DECLARE_KEY("Pragma", ' ', PRAGMA, validate, NULL, NULL),
  74         DECLARE_KEY("Public", ' ', PUBLIC, validate, NULL, NULL),
  75         DECLARE_KEY("Server", ' ', SERVER, validate, NULL, NULL),
  76 
  77         DECLARE_KEY("UA-Disp", ' ', UA_DISP, validate, NULL, NULL),
  78         DECLARE_KEY("X-Cache", ' ', X_CACHE, validate, NULL, NULL),
  79         DECLARE_KEY("Trailer", ' ', TRAILER, validate, NULL, NULL),
  80         DECLARE_KEY("Upgrade", ' ', UPGRADE, validate, NULL, NULL),
  81         DECLARE_KEY("Cookie2", ' ', COOKIE2, validate, NULL, NULL),
  82         DECLARE_KEY("Expires", ' ', EXPIRES, validate, NULL, NULL),
  83         DECLARE_KEY("Referer", ' ', REFERER, validate, NULL, NULL),
  84         DECLARE_KEY("Warning", ' ', WARNING, validate, NULL, NULL),
  85 
  86         DECLARE_KEY("X-Forwarded-For", ' ', X_FORWARDED_FOR,validate,NULL,NULL),
  87         DECLARE_KEY("X-Serial-Number", ' ', X_SERIAL_NUMBER,validate,NULL,NULL),
  88         DECLARE_KEY("Accept-Encoding", ' ', ACCEPT_ENCODING,validate,NULL,NULL),
  89         DECLARE_KEY("Accept-Language", ' ', ACCEPT_LANGUAGE,validate,NULL,NULL),
  90 
  91         DECLARE_KEY("UA-Color", ' ', UA_COLOR, validate, NULL, NULL),
  92         DECLARE_KEY("If-Match", ' ', IF_MATCH, validate, NULL, NULL),
  93         DECLARE_KEY("If-Range", ' ', IF_RANGE, validate, NULL, NULL),
  94         DECLARE_KEY("Location", ' ', LOCATION, validate, NULL, NULL),
  95         
  96         DECLARE_KEY("UA-Pixels", ' ', UA_PIXELS, validate, NULL, NULL),
  97         DECLARE_KEY("Client-ip", ' ', CLIENT_IP, validate, NULL, NULL),
  98 
  99         DECLARE_KEY("Content-Type", ',', CONTENT_TYPE, validate, NULL, NULL),
 100         DECLARE_KEY("Content-Base", ' ', CONTENT_BASE, validate, NULL, NULL),
 101         DECLARE_KEY("Max-Forwards", ' ', MAX_FORWARDS, validate, NULL, NULL),
 102         DECLARE_KEY("MIME-Version", ' ', MIME_VERSION, validate, NULL, NULL),
 103 
 104         DECLARE_KEY("Content-Length", ' ', CONTENT_LENGTH, validate, NULL,NULL),
 105         DECLARE_KEY("Accept-Charset", ' ', ACCEPT_CHARSET, validate, NULL,NULL),
 106 
 107         DECLARE_KEY("Last-Modified", ' ', LAST_MODIFIED, validate, NULL, NULL),
 108         DECLARE_KEY("Content-Range", ' ', CONTENT_RANGE, validate, NULL, NULL),
 109         DECLARE_KEY("Authorization", ' ', AUTHORIZATION, validate, NULL, NULL),
 110         DECLARE_KEY("Accept-Ranges", ' ', ACCEPT_RANGES, validate, NULL, NULL),
 111         DECLARE_KEY("Cache-Control", ' ', CACHE_CONTROL, validate, NULL, NULL),
 112         DECLARE_KEY("If-None-Match", ' ', IF_NONE_MATCH, validate, NULL, NULL),
 113 
 114         DECLARE_KEY("Transfer-Encoding", ' ', TRANSFER_ENCODING,
 115                         validate, NULL, NULL),
 116 
 117         DECLARE_KEY("If-Modified-Since", ' ', IF_MODIFIED_SINCE,
 118                         validate, NULL, NULL),
 119 
 120         DECLARE_KEY("Retry-After", ' ', RETRY_AFTER, validate, NULL, NULL),
 121         DECLARE_KEY("Set-Cookie2", ' ', SET_COOKIE2, validate, NULL, NULL),
 122         DECLARE_KEY("Content-MD5", ' ', CONTENT_MD5, validate, NULL, NULL),
 123 
 124 
 125         DECLARE_KEY("WWW-Authenticate", ' ', WWW_AUTHENTICATE,
 126                         validate, NULL, NULL),
 127         DECLARE_KEY("Proxy-Connection", ' ', PROXY_CONNECTION,
 128                         validate, NULL, NULL),
 129         DECLARE_KEY("Content-Encoding", ' ', CONTENT_ENCODING,
 130                         validate, NULL, NULL),
 131         DECLARE_KEY("Content-Language", ' ', CONTENT_LANGUAGE,
 132                         validate, NULL, NULL),
 133         DECLARE_KEY("Content-Location", ' ', CONTENT_LOCATION,
 134                         validate, NULL, NULL),
 135 
 136         DECLARE_KEY("Proxy-Authenticate", ' ', PROXY_AUTHENTICATE,
 137                         validate, NULL, NULL),
 138 
 139         DECLARE_KEY("If-Unmodified-Since", ' ', IF_UNMODIFIED_SINCE,
 140                         validate, NULL, NULL),
 141         DECLARE_KEY("Proxy-Authorization", ' ', PROXY_AUTHORIZATION,
 142                         validate, NULL, NULL),
 143         
 144         DECLARE_KEY("Status", ' ', STATUS, validate, NULL, NULL),
 145 
 146 };
 147 #undef DECLARE_KEY
 148 #undef http_header_parse_NULL
 149 
 150 #define DECLARE_RESPONSE_INTERNAL(_code, _msg)  \
 151         { (_msg), CONST_LEN(_msg), CONST_LEN(_msg), RH_BUFFER_CONST }
 152 
 153 #define DECLARE_RESPONSE(_code, _msg)   \
 154         DECLARE_RESPONSE_INTERNAL(_code, "HTTP/1.1 " _msg)
 155 
 156 /* idea of this response vector and its access method is based on apache */
 157 static const rh_buffer_t http_response[] = {
 158 
 159 #define HTTP_RESPONSE_100       0
 160         
 161         DECLARE_RESPONSE(100, "100 Continue"),
 162         DECLARE_RESPONSE(101, "101 Switching Protocols"),
 163 
 164 #define HTTP_RESPONSE_200       (HTTP_RESPONSE_100 + 2)
 165         
 166         DECLARE_RESPONSE(200, "200 OK"),
 167         DECLARE_RESPONSE(201, "201 Created"),
 168         DECLARE_RESPONSE(202, "202 Accepted"),
 169         DECLARE_RESPONSE(203, "203 Non-Authoritative Information"),
 170         DECLARE_RESPONSE(204, "204 No Content"),
 171         DECLARE_RESPONSE(205, "205 Reset Content"),
 172         DECLARE_RESPONSE(206, "206 Partial Content"),
 173         
 174 #define HTTP_RESPONSE_300       (HTTP_RESPONSE_200 + 7)
 175         
 176         DECLARE_RESPONSE(300, "300 Multiple Choices"),
 177         DECLARE_RESPONSE(301, "301 Moved Permanently"),
 178         DECLARE_RESPONSE(302, "302 Found"),
 179         DECLARE_RESPONSE(303, "303 See Other"),
 180         DECLARE_RESPONSE(304, "304 Not Modified"),
 181         DECLARE_RESPONSE(305, "305 Use Proxy"),
 182         DECLARE_RESPONSE(306, "306 (Unused)"),
 183         DECLARE_RESPONSE(307, "307 Temporary Redirect"),
 184 
 185 #define HTTP_RESPONSE_400       (HTTP_RESPONSE_300 + 8)
 186         
 187         DECLARE_RESPONSE(400, "400 Bad Request"),
 188         DECLARE_RESPONSE(401, "401 Unauthorized"),
 189         DECLARE_RESPONSE(402, "402 Payment Required"),
 190         DECLARE_RESPONSE(403, "403 Forbidden"),
 191         DECLARE_RESPONSE(404, "404 Not Found"),
 192         DECLARE_RESPONSE(405, "405 Method Not Allowed"),
 193         DECLARE_RESPONSE(406, "406 Not Acceptable"),
 194         DECLARE_RESPONSE(407, "407 Proxy Authentication Required"),
 195         DECLARE_RESPONSE(408, "408 Request Timeout"),
 196         DECLARE_RESPONSE(419, "419 Conflict"),
 197         DECLARE_RESPONSE(410, "410 Gone"),
 198         DECLARE_RESPONSE(411, "411 Length Required"),
 199         DECLARE_RESPONSE(412, "412 Precondition Failed"),
 200         DECLARE_RESPONSE(413, "413 Request Entity Too Large"),
 201         DECLARE_RESPONSE(414, "414 Request URI Too Long"),
 202         DECLARE_RESPONSE(415, "415 Unsupported Media Type"),
 203         DECLARE_RESPONSE(416, "416 Requested Range Not Satisfiable"),
 204         DECLARE_RESPONSE(417, "417 Expectation Failed"),
 205         
 206 #define HTTP_RESPONSE_500       (HTTP_RESPONSE_400 + 18)
 207         
 208         DECLARE_RESPONSE(500, "500 Internal Server Error"),
 209         DECLARE_RESPONSE(501, "501 Not Implemented"),
 210         DECLARE_RESPONSE(502, "502 Bad Gateway"),
 211         DECLARE_RESPONSE(503, "503 Service Unavailable"),
 212         DECLARE_RESPONSE(504, "504 Gateway Timeout"),
 213         DECLARE_RESPONSE(505, "505 HTTP Version Not Supported"),
 214 };
 215 
 216 #undef DECLARE_RESPONSE
 217 #undef DECLARE_RESPONSE_INTERNAL
 218 
 219 
 220 static http_status_t http_header_parse_entries (http_header_t *header);
 221 static http_status_t http_header_merge (http_header_t *header);
 222 
 223 static http_status_t http_header_parse_request (http_header_t *header);
 224 static const struct http_header_key * http_header_get_key (const char *key, size_t nkey);
 225 
 226 void http_header_init (http_header_t *header, int fullclear)
 227 {
 228         if (fullclear)
 229                 rh_bzero (header, sizeof(*header));
 230 
 231         TAILQ_INIT(&header->entries_raw);
 232         TAILQ_INIT(&header->entries_parsed);
 233         TAILQ_INIT(&header->entries_unknown);
 234 }
 235 
 236 static void http_header_destroy_entries (http_header_t *header,
 237                 struct http_header_entry_list *list)
 238 {
 239         for (;;) {
 240                 struct http_header_entry        *entry;
 241                 
 242                 entry = TAILQ_FIRST(list);
 243                 if (NULL == entry)
 244                         break;
 245 
 246                 TAILQ_REMOVE(list, entry, entries);
 247 
 248                 if (entry->data && entry->key->destroy) {
 249                         entry->key->destroy (entry);
 250                         entry->data = NULL;
 251                 }
 252 
 253                 if (entry->flags & HTTP_HEADER_KEY_FLAG_UNKNOWN) {
 254 
 255                 }
 256 #if 0
 257                 printf ("%s() [%.*s] = [%.*s]\n", __FUNCTION__,
 258                                 entry->key->nkey, entry->key->key,
 259                                 entry->value.used, entry->value.data );
 260 #endif
 261 
 262                 rh_buffer_destroy(&entry->value);
 263         }
 264 }
 265 
 266 void http_header_destroy (http_header_t *header)
 267 {
 268         uri_destroy (&header->uri);
 269 
 270         http_header_destroy_entries (header, &header->entries_raw);
 271         http_header_destroy_entries (header, &header->entries_parsed);
 272         http_header_destroy_entries (header, &header->entries_unknown);
 273         
 274         http_header_clear (header);
 275 }
 276 
 277 void http_header_dump (http_header_t *header)
 278 {
 279         struct http_header_entry *entry;
 280 
 281         TAILQ_FOREACH(entry, &header->entries_parsed, entries) {
 282                 DEBUGLOG("[%.*s]: [%.*s]",
 283                                 entry->key->nkey,
 284                                 entry->key->key,
 285                                 entry->value.used,
 286                                 entry->value.data);
 287         }
 288 }
 289 
 290 void http_header_reset (http_header_t *header)
 291 {
 292         http_header_destroy (header);
 293         http_header_init (header, 1);
 294 }
 295 
 296 http_status_t http_header_set_errno_status (http_header_t *header, int error)
 297 {
 298         switch (error) {
 299         case ENOENT:
 300                 return (header->status = HTTP_STATUS_404_NOT_FOUND);
 301         case EACCES:
 302         case ELOOP:
 303         case EROFS:
 304                 return (header->status = HTTP_STATUS_403_FORBIDDEN);
 305         case ENAMETOOLONG:
 306                 return (header->status = HTTP_STATUS_414_REQUEST_URI_TOO_LONG);
 307         case EMFILE:
 308         case ENOMEM:
 309         case ENOSPC:
 310         case EOVERFLOW:
 311                 return (header->status = HTTP_STATUS_503_SERVICE_UNAVAILABLE);
 312         default:
 313                 return (header->status = HTTP_STATUS_500_INTERNAL_SERVER_ERROR);
 314         }
 315 }
 316 
 317 int http_header_parse (http_header_t *header, int type,
 318                 const char *buffer, size_t nbuffer)
 319 {
 320         http_status_t   status;
 321         
 322 
 323         
 324         header->type = type;
 325         header->buffer = buffer;
 326         header->nbuffer = nbuffer;
 327 
 328         switch (type) {
 329         case HTTP_HEADER_SERVER:
 330                 status = http_header_parse_request (header);
 331                 if (status)
 332                         goto error_out;
 333                 break;
 334         default:
 335                 status = 500;
 336                 goto error_out;
 337         }
 338         
 339         /* merge lines */
 340         status = http_header_merge (header);
 341         if (status)
 342                 goto error_out;
 343         
 344         /* first (fast) parser */
 345         header->keepalive = -1;
 346         
 347         status = http_header_parse_entries (header);    
 348         if (status) {
 349                 header->keepalive = 0;
 350                 goto error_out;
 351         }
 352         
 353         /* keepalive header was not send.
 354          * set to true if >= http/1.1 otherwise off */
 355         if (-1 == header->keepalive) {
 356                 if (header->version > HTTP_VERSION_10) {
 357                         header->keepalive = 1;
 358                 } else {
 359                         header->keepalive = 0;
 360                 }
 361         }
 362 
 363         return 0;
 364 
 365 error_out:
 366         header->status = status;
 367         return -1;
 368 }
 369 
 370 static http_status_t http_header_parse_entries (http_header_t *header)
 371 {
 372         for (;;) {
 373                 http_header_entry_t     *entry;
 374                 http_status_t           status;
 375 
 376                 entry = TAILQ_FIRST(&header->entries_raw);
 377                 if (NULL == entry)
 378                         break;
 379 
 380                 entry->header = header;
 381 
 382                 status = entry->key->parse_first (entry);
 383                 if (status)
 384                         return status;
 385                 
 386                 TAILQ_REMOVE(&header->entries_raw, entry, entries);
 387                 TAILQ_INSERT_TAIL(&header->entries_parsed, entry, entries);
 388         }
 389         
 390         return 0;
 391 }
 392 
 393 /*
 394  *
 395  * http header keys must be merged because:
 396  * 
 397  * - there maybe more then one time the same key, eg:
 398  *      
 399  *      Connection: what=ever
 400  *      Host: something
 401  *      Connection: close
 402  *
 403  *      But this includes a problem:
 404  *              
 405  *              Cookie: First-Cookie
 406  *              Some-Other: Header
 407  *              Cookie: Second-Cookie and DIFFERENT cookie
 408  *              
 409  *      This means, sometimes headers should not merged,
 410  *      they should stored in a list.
 411  *
 412  *
 413  * - http/1.1 allows multiple lines, eg:
 414  *   
 415  *      Connection: what
 416  *        ever
 417  *          something more
 418  *      Host: localhorst
 419  *      Connection: close
 420  *
 421  *      Note: Apache did not remove the whitespace (expect the first?).
 422  *
 423  * Therefore the real parser can only called if ALL lines are merged.
 424  *
 425  */
 426 static http_status_t http_header_merge (http_header_t *header)
 427 {
 428         const struct http_header_key    *key_def = NULL;
 429         
 430         /*
 431          *
 432          * merge line by line
 433          *
 434          */
 435         for (;;) {
 436                 struct http_header_entry *entry;
 437                 const char      *line, *line_end;
 438                 size_t          nline;
 439                 const char      *key, *value;
 440                 size_t          nkey, nvalue;
 441 
 442                 line_end = memchr (header->buffer, '\n', header->nbuffer);
 443                 if (NULL == line_end)
 444                         return HTTP_STATUS_400_BAD_REQUEST;
 445 
 446                 line = header->buffer;
 447                 nline = line_end + 1 - line;
 448                 
 449 #if 0
 450                 printf ("raw-line: [%.*s]\n", nline, line);
 451 #endif
 452 
 453                 header->buffer += nline;
 454                 header->nbuffer -= nline;
 455 
 456                 if (nline < CONST_LEN(NL) || '\r' != line[nline-2])
 457                         return HTTP_STATUS_400_BAD_REQUEST;
 458 
 459                 nline -= CONST_LEN(NL);
 460 
 461                 if (0 == nline) {
 462                         if (header->nbuffer)
 463                                 return HTTP_STATUS_400_BAD_REQUEST;
 464                                 
 465                         break;
 466                 }
 467 
 468 
 469                 /*
 470                  *
 471                  * split "key: value"
 472                  *
 473                  * 
 474                  */
 475 
 476                 if (HTTP_ISSPACE(*line)) {
 477                         if (NULL == key_def)
 478                                 return HTTP_STATUS_400_BAD_REQUEST;
 479 
 480                         key = key_def->key;
 481                         nkey = key_def->nkey;
 482 
 483                         value = line + 1; /* without first space */
 484                         nvalue = nline - 1;
 485                 } else {
 486                         key = line;
 487                         
 488                         value = memchr (line, ':', nline);
 489                         if (NULL == value)
 490                                 return HTTP_STATUS_400_BAD_REQUEST;
 491 
 492                         nkey = value - key;
 493                         CONST_RTRIM(key, nkey, HTTP_ISSPACE);
 494 
 495                         value += CONST_LEN(":");
 496                         nvalue = nline - (value - line);
 497                 
 498                         key_def = http_header_get_key(key, nkey);
 499                 }
 500                         
 501                 CONST_LTRIM(value, nvalue, HTTP_ISSPACE);
 502                 CONST_RTRIM(value, nvalue, HTTP_ISSPACE);
 503 
 504                 if (NULL == key_def) {
 505                         /* ignorie: later -> append hashed */
 506                         printf ("skip header: [%.*s]\n", nline, line);
 507                         continue;
 508                 }
 509 
 510                 entry = &header->entries[key_def->type];
 511                 entry->key = key_def;
 512 
 513                 if (1 == ++entry->found) {
 514                         TAILQ_INSERT_TAIL(&header->entries_raw, entry, entries);
 515                 }
 516                 
 517                 if (entry->value.used) {
 518                         /* key is mergeable? */
 519                         /* XXX: remember the multiple "Cookie" Problem */
 520                         if (0 == key_def->merge_char)
 521                                 return HTTP_STATUS_400_BAD_REQUEST;
 522 
 523                         /* append merge char if neccesary */
 524                         if (    key_def->merge_char != rh_buffer_ch_last(
 525                                                 &entry->value) &&
 526                                 key_def->merge_char != value[0])
 527                         {
 528                                 if (rh_buffer_append_ch (&entry->value,
 529                                                         key_def->merge_char,
 530                                                         1) )
 531                                 {
 532                                         return 500;
 533                                 }
 534                         }
 535                 }
 536 
 537                 if (rh_buffer_append (&entry->value, value, nvalue))
 538                         return HTTP_STATUS_500_INTERNAL_SERVER_ERROR;
 539         }
 540 
 541         header->buffer = NULL;
 542         header->nbuffer = 0;
 543 
 544         return 0;
 545 }
 546 
 547 /*
 548  * parse client request line: "GET / HTTP/1.1"
 549  *
 550  */
 551 static http_status_t http_header_parse_request (http_header_t *header)
 552 {
 553         const char      *uri;
 554         size_t          nuri;
 555         const char      *version;
 556         
 557         if (header->nbuffer < CONST_LEN ("GET / HTTP/1.0\r\n"))
 558                 return HTTP_STATUS_400_BAD_REQUEST;
 559         
 560         if <