00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <assert.h>
00043 #include <stdio.h>
00044 #include <string.h>
00045
00046 #include "common/autobuf.h"
00047 #include "common/avl.h"
00048 #include "common/avl_comp.h"
00049 #include "common/string.h"
00050 #include "builddata/data.h"
00051 #include "olsr_logging.h"
00052 #include "olsr_memcookie.h"
00053 #include "olsr_comport.h"
00054 #include "olsr_comport_http.h"
00055 #include "olsr_comport_txt.h"
00056 #include "olsr_cfg.h"
00057 #include "ipcalc.h"
00058
00059 #define HTTP_TESTSITE
00060
00061 static const char HTTP_VERSION[] = "HTTP/1.0";
00062 static const char TELNET_PATH[] = "/telnet/";
00063
00064 static struct olsr_memcookie_info *htmlsite_cookie;
00065 struct avl_tree http_handler_tree;
00066
00068 static char http_200_response[] = "OK";
00069 static char http_400_response[] = "Bad Request";
00070 static char http_401_response[] = "Unauthorized";
00071 static char http_403_response[] = "Forbidden";
00072 static char http_404_response[] = "Not Found";
00073 static char http_413_response[] = "Request Entity Too Large";
00074 static char http_501_response[] = "Not Implemented";
00075 static char http_503_response[] = "Service Unavailable";
00076
00077 static bool parse_http_header(char *message, size_t message_len, struct http_request *request);
00078
00079
00080 #ifdef HTTP_TESTSITE
00081
00082 static void
00083 test_handler(struct comport_connection *con, struct http_request *request) {
00084 size_t i;
00085
00086 abuf_puts(&con->out, "<html><body>");
00087 abuf_appendf(&con->out, "<br>Request: %s</br>\n", request->method);
00088 abuf_appendf(&con->out, "<br>Filename: %s</br>\n", request->request_uri);
00089 abuf_appendf(&con->out, "<br>Http-Version: %s</br>\n", request->http_version);
00090
00091 for (i=0; i<request->query_count; i++) {
00092 abuf_appendf(&con->out, "<br>URL-Parameter: %s = %s</br>\n", request->query_name[i], request->query_value[i]);
00093 }
00094 for (i=0; i<request->header_count; i++) {
00095 abuf_appendf(&con->out, "<br>Header: %s = %s</br>\n", request->header_name[i], request->header_value[i]);
00096 }
00097 abuf_puts(&con->out, "</body></html>");
00098 }
00099
00100 static void init_test(void) {
00101 static char content[] = "<html><body>Yes, you got it !</body></html>";
00102 static char acl[] = "d2lraTpwZWRpYQ==";
00103 static char *aclPtr[] = { acl };
00104 struct olsr_html_site *site;
00105
00106 site = olsr_com_add_htmlsite("/", content, strlen(content));
00107 olsr_com_set_htmlsite_acl_auth(site, NULL, 1, aclPtr);
00108
00109 olsr_com_add_htmlhandler(test_handler, "/print/");
00110 }
00111 #endif
00112
00113 static void
00114 olsr_com_html2telnet_gate(struct comport_connection *con, struct http_request *request) {
00115 if (strlen(request->request_uri) > strlen(TELNET_PATH)) {
00116 char *cmd = &request->request_uri[strlen(TELNET_PATH)];
00117 char *next;
00118 size_t count = 1;
00119 enum olsr_txtcommand_result result;
00120
00121 while (cmd) {
00122 next = strchr(cmd, '/');
00123 if (next) {
00124 *next++ = 0;
00125 }
00126
00127 result = olsr_com_handle_txtcommand(con, cmd, request->query_count > count ? request->query_value[count] : NULL);
00128
00129
00130 if (result == CONTINOUS) {
00131 con->stop_handler(con);
00132 }
00133 else if (result == UNKNOWN) {
00134 abuf_appendf(&con->out, "Unknown command %s\n", cmd);
00135 con->send_as = HTTP_404_NOT_FOUND;
00136 }
00137 else if (result != CONTINUE) {
00138 abuf_appendf(&con->out, "Http-Telnet gate had problems with command %s\n", cmd);
00139 con->send_as = HTTP_400_BAD_REQ;
00140 }
00141 cmd = next;
00142 count ++;
00143 }
00144 }
00145 }
00146
00147 void
00148 olsr_com_init_http(void) {
00149 avl_init(&http_handler_tree, &avl_comp_strcasecmp, false, NULL);
00150
00151 htmlsite_cookie = olsr_memcookie_add("comport http sites", sizeof(struct olsr_html_site));
00152
00153
00154 olsr_com_add_htmlhandler(olsr_com_html2telnet_gate, TELNET_PATH);
00155 #ifdef HTTP_TESTSITE
00156 init_test();
00157 #endif
00158 }
00159
00160 void olsr_com_destroy_http(void) {
00161 struct olsr_html_site *site, *iterator;
00162
00163 OLSR_FOR_ALL_HTML_ENTRIES(site, iterator) {
00164 olsr_com_remove_htmlsite(site);
00165 }
00166 }
00167
00168 struct olsr_html_site *
00169 olsr_com_add_htmlsite(const char *path, const char *content, size_t length) {
00170 struct olsr_html_site *site;
00171
00172 site = olsr_memcookie_malloc(htmlsite_cookie);
00173 site->path = strdup(path);
00174 site->node.key = site->path;
00175
00176 site->static_site = true;
00177 site->site_data = content;
00178 site->site_length = length;
00179
00180 avl_insert(&http_handler_tree, &site->node);
00181 return site;
00182 }
00183
00184 struct olsr_html_site *
00185 olsr_com_add_htmlhandler(void(*sitehandler)(struct comport_connection *con, struct http_request *request),
00186 const char *path) {
00187 struct olsr_html_site *site;
00188
00189 site = olsr_memcookie_malloc(htmlsite_cookie);
00190 site->node.key = strdup(path);
00191
00192 site->static_site = false;
00193 site->sitehandler = sitehandler;
00194
00195 avl_insert(&http_handler_tree, &site->node);
00196 return site;
00197 }
00198
00199 void
00200 olsr_com_remove_htmlsite(struct olsr_html_site *site) {
00201 avl_delete(&http_handler_tree, &site->node);
00202 free(site->path);
00203 olsr_memcookie_free(htmlsite_cookie, site);
00204 }
00205
00206 void
00207 olsr_com_set_htmlsite_acl_auth(struct olsr_html_site *site, struct ip_acl *ipacl, int auth_count, char **auth_entries) {
00208 site->acl = ipacl;
00209 site->auth_count = auth_count;
00210 site->auth = auth_entries;
00211 }
00212
00213
00214
00215
00216 static bool
00217 olsr_com_handle_htmlsite(struct comport_connection *con, char *path,
00218 struct http_request *request) {
00219 char *str;
00220 int i;
00221 struct olsr_html_site *site;
00222
00223 site = (struct olsr_html_site *)avl_find(&http_handler_tree, path);
00224 if (site == NULL) {
00225 OLSR_DEBUG(LOG_COMPORT, "No httphandler found for path %s\n", path);
00226 return false;
00227 }
00228
00229
00230 if (site->auth) {
00231
00232 char key[256] = { 0 };
00233
00234 con->send_as = HTTP_401_UNAUTHORIZED;
00235
00236 str = strstr(con->in.buf, "\nAuthorization: Basic ");
00237 if (str != NULL && sscanf(str + 1, "%*s %*s %s\n", key) == 1) {
00238 OLSR_DEBUG(LOG_COMPORT, "ACL string received: %s\n", key);
00239 for (i = 0; i < site->auth_count; i++) {
00240 if (strcmp(site->auth[i], key) == 0) {
00241 con->send_as = HTTP_200_OK;
00242 break;
00243 }
00244 }
00245 }
00246 if (con->send_as == HTTP_401_UNAUTHORIZED) {
00247 OLSR_DEBUG(LOG_COMPORT, "Error, invalid authorization\n");
00248 return true;
00249 }
00250 }
00251
00252
00253 if (site->acl != NULL && !ip_acl_acceptable(site->acl, &con->addr, olsr_cnf->ip_version)) {
00254 #if !defined(REMOVE_LOG_DEBUG)
00255 struct ipaddr_str buf;
00256 #endif
00257 con->send_as = HTTP_403_FORBIDDEN;
00258 OLSR_DEBUG(LOG_COMPORT, "Error, access by IP %s is not allowed for path %s\n",
00259 path, olsr_ip_to_string(&buf, &con->addr));
00260 return true;
00261 }
00262
00263
00264 if (site->static_site) {
00265 abuf_memcpy(&con->out, site->site_data, site->site_length);
00266 } else {
00267 site->sitehandler(con, request);
00268 }
00269 con->send_as = HTTP_200_OK;
00270 return true;
00271 }
00272
00273 static bool parse_http_header(char *message, size_t message_len, struct http_request *request) {
00274 size_t header_index;
00275
00276 assert(message);
00277 assert(request);
00278
00279 memset(request, 0, sizeof(struct http_request));
00280 request->method = message;
00281
00282 while(true) {
00283 if (message_len < 2) {
00284 goto unexpected_end;
00285 }
00286
00287 if (*message == ' ' && request->http_version == NULL) {
00288 *message = '\0';
00289
00290 if (request->request_uri == NULL) {
00291 request->request_uri = &message[1];
00292 }
00293 else if (request->http_version == NULL) {
00294 request->http_version = &message[1];
00295 }
00296 }
00297 else if (*message == '\r') {
00298 *message = '\0';
00299 }
00300 else if (*message == '\n') {
00301 *message = '\0';
00302
00303 message++; message_len--;
00304 break;
00305 }
00306
00307 message++; message_len--;
00308 }
00309
00310 if (request->http_version == NULL) {
00311 goto unexpected_end;
00312 }
00313
00314 for(header_index = 0; true; header_index++) {
00315 if (message_len < 1) {
00316 goto unexpected_end;
00317 }
00318
00319 if (*message == '\n') {
00320 break;
00321 }
00322 else if (*message == '\r') {
00323 if (message_len < 2) return true;
00324
00325 if (message[1] == '\n') {
00326 break;
00327 }
00328 }
00329
00330 if (header_index >= MAX_HTTP_HEADERS) {
00331 goto too_many_fields;
00332 }
00333
00334 request->header_name[header_index] = message;
00335
00336 while(true) {
00337 if (message_len < 1) {
00338 goto unexpected_end;
00339 }
00340
00341 if (*message == ':') {
00342 *message = '\0';
00343
00344 message++; message_len--;
00345 break;
00346 }
00347 else if (*message == ' ' || *message == '\t') {
00348 *message = '\0';
00349 }
00350 else if (*message == '\n' || *message == '\r') {
00351 goto unexpected_end;
00352 }
00353
00354 message++; message_len--;
00355 }
00356
00357 while(true) {
00358 if (message_len < 1) {
00359 goto unexpected_end;
00360 }
00361
00362 if (request->header_value[header_index] == NULL) {
00363 if (*message != ' ' && *message != '\t') {
00364 request->header_value[header_index] = message;
00365 }
00366 }
00367
00368 if (*message == '\n') {
00369 if (message_len < 2) {
00370 goto unexpected_end;
00371 }
00372
00373 if (message[1] == ' ' || message[1] == '\t') {
00374 *message = ' ';
00375 message[1] = ' ';
00376
00377 message += 2; message_len -= 2;
00378 continue;
00379 }
00380
00381 *message = '\0';
00382
00383 if (request->header_value[header_index] == NULL) {
00384 request->header_value[header_index] = message;
00385 }
00386
00387 message++; message_len--;
00388 break;
00389 }
00390 else if (*message == '\r') {
00391 if (message_len < 2) {
00392 goto unexpected_end;
00393 }
00394
00395 if (message[1] == '\n') {
00396 if (message_len < 3) {
00397 goto unexpected_end;
00398 }
00399
00400 if (message[2] == ' ' || message[2] == '\t') {
00401 *message = ' ';
00402 message[1] = ' ';
00403 message[2] = ' ';
00404
00405 message += 3; message_len -= 3;
00406 continue;
00407 }
00408
00409 *message = '\0';
00410
00411 if (request->header_value[header_index] == NULL) {
00412 request->header_value[header_index] = message;
00413 }
00414
00415 message += 2; message_len -= 2;
00416 break;
00417 }
00418 }
00419
00420 message++; message_len--;
00421 }
00422 }
00423
00424 request->header_count = header_index;
00425 return false;
00426
00427 too_many_fields:
00428 OLSR_DEBUG(LOG_COMPORT, "Error, too many HTTP header fields\n");
00429 return true;
00430
00431 unexpected_end:
00432 OLSR_DEBUG(LOG_COMPORT, "Error, unexpected end of HTTP header\n");
00433 return true;
00434 }
00435
00436 static size_t parse_query_string(char *s, char **name, char **value, size_t count) {
00437 char *ptr;
00438 size_t i = 0;
00439
00440 assert(s);
00441 assert(name);
00442 assert(value);
00443
00444 while (s != NULL && i < count) {
00445 name[i] = s;
00446
00447 s = strchr(s, '&');
00448 if (s != NULL) {
00449 *s++ = '\0';
00450 }
00451
00452 ptr = strchr(name[i], '=');
00453 if (ptr != NULL) {
00454 *ptr++ = '\0';
00455 value[i] = ptr;
00456 } else {
00457 value[i] = &name[i][strlen(name[i])];
00458 }
00459
00460 if(name[i][0] != '\0') {
00461 i++;
00462 }
00463 }
00464
00465 return i;
00466 }
00467
00468 void olsr_com_parse_http(struct comport_connection *con,
00469 unsigned int flags __attribute__ ((unused))) {
00470 struct http_request request;
00471 char *para = NULL, *str = NULL;
00472 char processed_filename[256];
00473 size_t idx = 0;
00474 size_t i = 0;
00475
00476
00477
00478
00479
00480
00481 while (i < 5) {
00482 switch (con->in.buf[idx++]) {
00483 case '\0':
00484 i = 6;
00485 break;
00486 case '\r':
00487 i = (i == 3) ? 4 : 2;
00488 break;
00489 case '\n':
00490 if (i == 1 || i == 4) {
00491 i = 5;
00492 } else if (i == 2) {
00493 i = 3;
00494 } else {
00495 i = 1;
00496 }
00497 break;
00498 default:
00499 i = 0;
00500 break;
00501 }
00502 }
00503
00504 if (i != 5) {
00505 OLSR_DEBUG(LOG_COMPORT, " need end of http header, still waiting...\n");
00506 return;
00507 }
00508
00509
00510
00511 if (parse_http_header(con->in.buf, con->in.len, &request)) {
00512 OLSR_DEBUG(LOG_COMPORT, "Error, illegal http header.\n");
00513 con->send_as = HTTP_400_BAD_REQ;
00514 con->state = SEND_AND_QUIT;
00515 return;
00516 }
00517
00518 if (strcasecmp(request.http_version, "HTTP/1.1") != 0 && strcasecmp(request.http_version, "HTTP/1.0") != 0) {
00519 OLSR_DEBUG(LOG_COMPORT, "Unknown Http-Version: '%s'\n", request.http_version);
00520 con->send_as = HTTP_400_BAD_REQ;
00521 con->state = SEND_AND_QUIT;
00522 return;
00523 }
00524
00525 OLSR_DEBUG(LOG_COMPORT, "HTTP Request: %s %s %s\n", request.method, request.request_uri, request.http_version);
00526
00527
00528 strscpy(processed_filename, request.request_uri, sizeof(processed_filename));
00529 if (strcmp(request.method, "POST") == 0) {
00530
00531 int clen;
00532
00533 for (i=0, clen=-1; i<request.header_count; i++) {
00534 if (strcasecmp(request.header_name[i], "Content-Length") == 0) {
00535 clen = atoi(request.header_value[i]);
00536 break;
00537 }
00538 }
00539
00540 if (clen == -1) {
00541 con->send_as = HTTP_400_BAD_REQ;
00542 con->state = SEND_AND_QUIT;
00543 return;
00544 }
00545
00546 if (con->in.len < idx + clen) {
00547
00548 return;
00549 }
00550
00551 request.form_count = parse_query_string(&con->in.buf[idx], request.form_name, request.form_value, MAX_HTTP_FORM);
00552 }
00553
00554
00555 str = strchr(processed_filename, '#');
00556 if (str) {
00557 *str = 0;
00558 }
00559
00560
00561 con->state = SEND_AND_QUIT;
00562 olsr_com_decode_url(processed_filename);
00563
00564 if (strcmp(request.method, "GET") == 0) {
00565
00566 para = strchr(processed_filename, '?');
00567 if (para != NULL) {
00568 *para++ = 0;
00569 request.query_count = parse_query_string(para, request.query_name, request.query_value, MAX_HTTP_QUERY);
00570 }
00571 } else if (strcmp(request.method, "POST") != 0) {
00572 con->send_as = HTTP_501_NOT_IMPLEMENTED;
00573 return;
00574 }
00575
00576
00577 i = strlen(processed_filename);
00578
00579
00580
00581
00582
00583 if (processed_filename[i - 1] != '/' && request.query_count == 0) {
00584 strcat(processed_filename, "/");
00585 }
00586
00587 while (i > 0) {
00588 if (olsr_com_handle_htmlsite(con, processed_filename, &request)) {
00589 return;
00590 }
00591
00592
00593 if (i > 0 && processed_filename[i] == '/') {
00594 processed_filename[i--] = 0;
00595 }
00596 else {
00597 do {
00598 processed_filename[i--] = 0;
00599 } while (i > 0 && processed_filename[i] != '/');
00600 }
00601 }
00602 con->send_as = HTTP_404_NOT_FOUND;
00603 }
00604
00605 void
00606 olsr_com_build_httpheader(struct comport_connection *con) {
00607 struct autobuf buf;
00608 time_t currtime;
00609
00610 abuf_init(&buf, 1024);
00611
00612 abuf_appendf(&buf, "%s %d %s\r\n", HTTP_VERSION, con->send_as, olsr_com_get_http_message(con->send_as));
00613
00614
00615 time(&currtime);
00616 abuf_strftime(&buf, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
00617
00618
00619 abuf_appendf(&buf, "Server: %s %s %s %s\r\n",
00620 get_olsrd_version(), get_olsrd_builddate(), get_olsrd_buildsystem(), HTTP_VERSION);
00621
00622
00623 abuf_puts(&buf, "Connection: closed\r\n");
00624
00625
00626 if (con->http_contenttype == NULL) {
00627 con->http_contenttype = con->send_as != HTTP_PLAIN ? "text/html" : "text/plain";
00628 }
00629 abuf_appendf(&buf, "Content-type: %s\r\n", con->http_contenttype);
00630
00631
00632 if (con->out.len > 0) {
00633 abuf_appendf(&buf, "Content-length: %zu\r\n", con->out.len);
00634 }
00635
00636 if (con->send_as == HTTP_401_UNAUTHORIZED) {
00637 abuf_appendf(&buf, "WWW-Authenticate: Basic realm=\"%s\"\r\n", "RealmName");
00638 }
00639
00640
00641
00642 abuf_puts(&buf, "Cache-Control: no-cache\r\n");
00643
00644 if (con->send_as == HTTP_PLAIN) {
00645 abuf_puts(&buf, "Accept-Ranges: bytes\r\n");
00646 }
00647
00648 abuf_puts(&buf, "\r\n");
00649
00650 abuf_memcpy_prefix(&con->out, buf.buf, buf.len);
00651 OLSR_DEBUG(LOG_PLUGINS, "HEADER:\n%s", buf.buf);
00652
00653 abuf_free(&buf);
00654 }
00655
00656 void
00657 olsr_com_create_httperror(struct comport_connection *con) {
00658 abuf_appendf(&con->out, "<body><h1>HTTP error %d: %s</h1></body>", con->send_as, olsr_com_get_http_message(con->send_as));
00659 }
00660
00661 char *
00662 olsr_com_get_http_message(enum http_header_type type) {
00663 static char nothing[] = "";
00664
00665 switch (type) {
00666 case HTTP_PLAIN:
00667 case HTTP_200_OK:
00668 return http_200_response;
00669 case HTTP_400_BAD_REQ:
00670 return http_400_response;
00671 case HTTP_401_UNAUTHORIZED:
00672 return http_401_response;
00673 case HTTP_403_FORBIDDEN:
00674 return http_403_response;
00675 case HTTP_404_NOT_FOUND:
00676 return http_404_response;
00677 case HTTP_413_REQUEST_TOO_LARGE:
00678 return http_413_response;
00679 case HTTP_501_NOT_IMPLEMENTED:
00680 return http_501_response;
00681 case HTTP_503_SERVICE_UNAVAILABLE:
00682 return http_503_response;
00683 default:
00684 return nothing;
00685 }
00686 }
00687
00688 void olsr_com_decode_url(char *str) {
00689 char *dst = str;
00690
00691 while (*str) {
00692 if (*str == '%' && str[1] && str[2]) {
00693 int value = 0;
00694
00695 str++;
00696 sscanf(str, "%02x", &value);
00697 *dst++ = (char) value;
00698 str += 2;
00699 } else {
00700 *dst++ = *str++;
00701 }
00702 }
00703 *dst = 0;
00704 }