3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of olsr.org, olsrd nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * Visit http://www.olsr.org for more information.
36 * If you find this software useful feel free to make a donation
37 * to the project. For more information see the website or contact
38 * the copyright holders.
43 #include "common/autobuf.h"
44 #include "common/avl.h"
45 #include "olsr_logging.h"
46 #include "olsr_cookie.h"
47 #include "olsr_comport.h"
48 #include "olsr_comport_http.h"
51 #define HTTP_VERSION "HTTP/1.1"
53 static struct avl_tree http_handler_tree;
54 static struct olsr_cookie_info *htmlsite_cookie;
57 static char http_200_response[] = "OK";
58 static char http_400_response[] = "Bad Request";
59 static char http_401_response[] = "Unauthorized";
60 static char http_403_response[] = "Forbidden";
61 static char http_404_response[] = "Not Found";
62 static char http_413_response[] = "Request Entity Too Large";
63 static char http_501_response[] = "Not Implemented";
64 static char http_503_response[] = "Service Unavailable";
66 /* sample for a static html page */
67 static void init_test(void) {
68 static char content[] = "<html><body>Yes, you got it !</body></html>";
69 static char path[] = "/";
70 static char acl[] = "d2lraTpwZWRpYQ=="; /* base 64 .. this is "wikipedia" */
71 static char *aclPtr[] = { acl };
72 struct olsr_html_site *site;
74 site = olsr_com_add_htmlsite(path, content, strlen(content));
75 olsr_com_set_htmlsite_acl_auth(site, NULL, 1, aclPtr);
79 olsr_com_init_http(void) {
80 avl_init(&http_handler_tree, &avl_comp_strcasecmp);
82 htmlsite_cookie = olsr_alloc_cookie("comport http sites", OLSR_COOKIE_TYPE_MEMORY);
83 olsr_cookie_set_memory_size(htmlsite_cookie, sizeof(struct olsr_html_site));
88 struct olsr_html_site *
89 olsr_com_add_htmlsite(char *path, char *content, size_t length) {
90 struct olsr_html_site *site;
92 site = olsr_cookie_malloc(htmlsite_cookie);
93 site->node.key = strdup(path);
95 site->static_site = true;
96 site->site_data = content;
97 site->site_length = length;
99 avl_insert(&http_handler_tree, &site->node, AVL_DUP_NO);
103 struct olsr_html_site *
104 olsr_com_add_htmlhandler(void(*sitehandler)(struct autobuf *buf, char *path, int parameter_count, char *parameters[]),
106 struct olsr_html_site *site;
108 site = olsr_cookie_malloc(htmlsite_cookie);
109 site->node.key = strdup(path);
111 site->static_site = false;
112 site->sitehandler = sitehandler;
114 avl_insert(&http_handler_tree, &site->node, AVL_DUP_NO);
119 olsr_com_remove_htmlsite(struct olsr_html_site *site) {
120 avl_delete(&http_handler_tree, &site->node);
121 free(site->node.key);
122 olsr_cookie_free(htmlsite_cookie, site);
126 olsr_com_set_htmlsite_acl_auth(struct olsr_html_site *site, struct ip_acl *ipacl, int auth_count, char **auth_entries) {
128 site->auth_count = auth_count;
129 site->auth = auth_entries;
132 /* handle the html site. returns true on successful handling (even if it was unauthorized)
133 * false if we did not find a site
136 olsr_com_handle_htmlsite(struct comport_connection *con, char *path,
137 char *fullpath, int para_count, char **para) {
140 struct olsr_html_site *site;
142 site = (struct olsr_html_site *)avl_find(&http_handler_tree, path);
147 /* check if username/password is necessary */
149 /* test for correct ACL */
150 char key[256] = { 0 };
152 con->send_as = HTTP_401_UNAUTHORIZED;
154 str = strstr(con->in.buf, "\nAuthorization: Basic ");
155 if (str != NULL && sscanf(str + 1, "%*s %*s %s\n", key) == 1) {
156 OLSR_DEBUG(LOG_COMPORT, "ACL string received: %s\n", key);
157 for (i = 0; i < site->auth_count; i++) {
158 if (strcmp(site->auth[i], key) == 0) {
159 con->send_as = HTTP_200_OK;
164 if (con->send_as == HTTP_401_UNAUTHORIZED) {
169 /* check if ip is allowed */
170 if (site->acl != NULL && !ip_acl_acceptable(site->acl, &con->addr, olsr_cnf->ip_version)) {
171 con->send_as = HTTP_403_FORBIDDEN;
175 /* call site handler */
176 if (site->static_site) {
177 abuf_memcpy(&con->out, site->site_data, site->site_length);
179 site->sitehandler(&con->out, fullpath, para_count, para);
181 con->send_as = HTTP_200_OK;
186 olsr_com_build_httpheader(struct comport_connection *con) {
190 abuf_init(&buf, 1024);
192 abuf_appendf(&buf, "%s %d %s\r\n", HTTP_VERSION, con->send_as, olsr_com_get_http_message(con->send_as));
196 abuf_strftime(&buf, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
199 abuf_appendf(&buf, "Server: %s %s %s %s\r\n", olsrd_version, build_date, build_host, HTTP_VERSION);
201 /* connection-type */
202 abuf_puts(&buf, "Connection: closed\r\n");
205 abuf_appendf(&buf, "Content-type: text/%s\r\n", con->send_as != HTTP_PLAIN ? "html" : "plain");
208 if (con->out.len > 0) {
209 abuf_appendf(&buf, "Content-length: %u\r\n", con->out.len);
212 if (con->send_as == HTTP_401_UNAUTHORIZED) {
213 abuf_appendf(&buf, "WWW-Authenticate: Basic realm=\"%s\"\r\n", "RealmName");
216 * No caching dynamic pages
218 abuf_puts(&buf, "Cache-Control: no-cache\r\n");
220 if (con->send_as == HTTP_PLAIN) {
221 abuf_puts(&buf, "Accept-Ranges: bytes\r\n");
224 abuf_puts(&buf, "\r\n");
226 abuf_memcpy_prefix(&con->out, buf.buf, buf.len);
227 OLSR_DEBUG(LOG_PLUGINS, "HEADER:\n%s", buf.buf);
233 olsr_com_create_httperror(struct comport_connection *con) {
234 abuf_appendf(&con->out, "<body><h1>HTTP error %d: %s</h1></body>", con->send_as, olsr_com_get_http_message(con->send_as));
238 olsr_com_get_http_message(enum http_header_type type) {
239 static char nothing[] = "";
244 return http_200_response;
245 case HTTP_400_BAD_REQ:
246 return http_400_response;
247 case HTTP_401_UNAUTHORIZED:
248 return http_401_response;
249 case HTTP_403_FORBIDDEN:
250 return http_403_response;
251 case HTTP_404_NOT_FOUND:
252 return http_404_response;
253 case HTTP_413_REQUEST_TOO_LARGE:
254 return http_413_response;
255 case HTTP_501_NOT_IMPLEMENTED:
256 return http_501_response;
257 case HTTP_503_SERVICE_UNAVAILABLE:
258 return http_503_response;
264 void olsr_com_decode_url(char *str) {
272 sscanf(str, "%02x", &value);
273 *dst++ = (char) value;