[Olsr-dev] [PATCH] jsoninfo: HTTP headers with CORS (if requested)
Ferry Huberts
(spam-protected)
Fri May 16 18:16:11 CEST 2014
On 16/05/14 18:13, Ferry Huberts wrote:
> there still are no overrun checks in the build_http_header. check the
> snprintf man page and pay very close attention to the 'return value'
> section.
>
> if there is an overrun, you have a heartbleed like bug: you increase
> size higher and higher, resulting in random memory being output.
>
> which is why I asked for usage of abuf
I think you can avoid the checks by determining the absolute minimum
length you would ever need. then add that as a big fat comment to the
buffer length define, together with an explanation.
>
> On 16/05/14 17:59, Alessio Caiazza wrote:
>> The new "httpheaders" parameter prepends HTTP headers to the reply.
>> If not set it will default to "no" and have the same behaviour as before.
>> Cross-origin resource sharing headers (CORS) are included in reply
>> allowing the
>> json retrieval by javascript applications not served by olsrd itself.
>> This will allow to easily develop js applications running directly in the
>> browser.
>> ---
>> lib/jsoninfo/README_JSONINFO | 8 +++++
>> lib/jsoninfo/src/olsrd_jsoninfo.c | 68
>> +++++++++++++++++++++++++++++++++++++--
>> lib/jsoninfo/src/olsrd_jsoninfo.h | 1 +
>> lib/jsoninfo/src/olsrd_plugin.c | 17 ++++++++++
>> 4 files changed, 91 insertions(+), 3 deletions(-)
>>
>> diff --git a/lib/jsoninfo/README_JSONINFO b/lib/jsoninfo/README_JSONINFO
>> index a102a56..4e63859 100644
>> --- a/lib/jsoninfo/README_JSONINFO
>> +++ b/lib/jsoninfo/README_JSONINFO
>> @@ -73,6 +73,14 @@ LoadPlugin "olsrd_jsoninfo.so.0.0"
>> # if you set it to 0.0.0.0, it will accept all connections
>> #PlParam "accept" "0.0.0.0"
>>
>> + # The "httpheaders" parameter prepends HTTP headers to the reply.
>> + # If not set it will default to "no" and have the same behaviour
>> as before.
>> + # Among with a minimal set of headers also Cross-origin resource
>> sharing
>> + # headers (CORS) are included in reply allowing the json
>> retrieval by
>> + # javascript applications not served by olsrd itself.
>> + # You can enable it uncommenting the following line:
>> + #PlParam "httpheaders" "yes"
>> +
>> # specify a UUID for this node to track it for debugging
>> #PlParam "UUIDFile" "/etc/olsrd/olsrd.uuid"
>> }
>> diff --git a/lib/jsoninfo/src/olsrd_jsoninfo.c
>> b/lib/jsoninfo/src/olsrd_jsoninfo.c
>> index 9db99b8..c9d1284 100644
>> --- a/lib/jsoninfo/src/olsrd_jsoninfo.c
>> +++ b/lib/jsoninfo/src/olsrd_jsoninfo.c
>> @@ -96,6 +96,9 @@
>>
>> static int ipc_socket;
>>
>> +/**Response types */
>> +#define HTTP_200 "HTTP/1.1 200 OK"
>> +
>> /* IPC initialization function */
>> static int plugin_ipc_init(void);
>>
>> @@ -126,6 +129,9 @@ static void ipc_print_interfaces(struct autobuf *);
>> static void ipc_print_plugins(struct autobuf *);
>> static void ipc_print_olsrd_conf(struct autobuf *abuf);
>>
>> +static size_t build_http_header(const char *status, const char *mime,
>> + uint32_t msgsize, char *buf, uint32_t bufsize);
>> +
>> #define TXT_IPC_BUFSIZE 256
>>
>> /* these provide all of the runtime status info */
>> @@ -151,6 +157,7 @@ static void ipc_print_olsrd_conf(struct autobuf
>> *abuf);
>> #define SIW_OLSRD_CONF 0x1000
>>
>> #define MAX_CLIENTS 3
>> +#define MAX_HTTPHEADER_SIZE 1024
>>
>> static char *outbuffer[MAX_CLIENTS];
>> static size_t outbuffer_size[MAX_CLIENTS];
>> @@ -1282,6 +1289,9 @@ static void
>> send_info(unsigned int send_what, int the_socket)
>> {
>> struct autobuf abuf;
>> + size_t header_len = 0;
>> + char header_buf[MAX_HTTPHEADER_SIZE];
>> + const char *content_type = "application/json";
>>
>> /* global variables for tracking when to put a comma in for JSON */
>> entrynumber[0] = 0;
>> @@ -1320,12 +1330,17 @@ send_info(unsigned int send_what, int the_socket)
>> ipc_print_olsrd_conf(&abuf);
>> }
>>
>> - outbuffer[outbuffer_count] = olsr_malloc(abuf.len, "txt output
>> buffer");
>> - outbuffer_size[outbuffer_count] = abuf.len;
>> + if(http_headers) {
>> + header_len = build_http_header(HTTP_200, content_type, abuf.len,
>> header_buf, sizeof(header_buf));
>> + }
>> +
>> + outbuffer[outbuffer_count] = olsr_malloc(header_len + abuf.len,
>> "json output buffer");
>> + outbuffer_size[outbuffer_count] = header_len + abuf.len;
>> outbuffer_written[outbuffer_count] = 0;
>> outbuffer_socket[outbuffer_count] = the_socket;
>>
>> - memcpy(outbuffer[outbuffer_count], abuf.buf, abuf.len);
>> + memcpy(outbuffer[outbuffer_count], header_buf, header_len);
>> + memcpy((outbuffer[outbuffer_count]) + header_len, abuf.buf, abuf.len);
>> outbuffer_count++;
>>
>> if (outbuffer_count == 1) {
>> @@ -1340,6 +1355,53 @@ send_info(unsigned int send_what, int the_socket)
>> abuf_free(&abuf);
>> }
>>
>> +static size_t
>> +build_http_header(const char *status, const char *mime, uint32_t
>> msgsize,
>> + char *buf, uint32_t bufsize)
>> +{
>> + time_t currtime;
>> + size_t size;
>> +
>> + size = snprintf(buf, bufsize, "%s\r\n", status);
>> +
>> + /* Date */
>> + time(&currtime);
>> + size += strftime(&buf[size], bufsize - size, "Date: %a, %d %b %Y
>> %H:%M:%S GMT\r\n", localtime(&currtime));
>> +
>> + /* Server version */
>> + size += snprintf(&buf[size], bufsize - size, "Server: OLSRD
>> JSONInfo plugin\r\n");
>> +
>> + /* connection-type */
>> + size += snprintf(&buf[size], bufsize - size, "Connection:
>> closed\r\n");
>> +
>> + /* MIME type */
>> + if(mime != NULL) {
>> + size += snprintf(&buf[size], bufsize - size, "Content-type:
>> %s\r\n", mime);
>> + }
>> +
>> + /* CORS data */
>> + /**No needs to be strict here, access control is based on source IP*/
>> + size += snprintf(&buf[size], bufsize - size,
>> "Access-Control-Allow-Origin: *\r\n");
>> + size += snprintf(&buf[size], bufsize - size,
>> "Access-Control-Allow-Methods: GET, POST, OPTIONS\r\n");
>> + size += snprintf(&buf[size], bufsize - size,
>> "Access-Control-Allow-Headers: Accept, Origin, X-Requested-With\r\n");
>> + size += snprintf(&buf[size], bufsize - size,
>> "Access-Control-Max-Age: 1728000\r\n");
>> +
>> + /* Content length */
>> + if (msgsize > 0) {
>> + size += snprintf(&buf[size], bufsize - size, "Content-length:
>> %i\r\n", msgsize);
>> + }
>> +
>> + /* Cache-control
>> + * No caching dynamic pages
>> + */
>> + size += snprintf(&buf[size], bufsize - size, "Cache-Control:
>> no-cache\r\n");
>> +
>> + /* End header */
>> + size += snprintf(&buf[size], bufsize - size, "\r\n");
>> +
>> + return size;
>> +}
>> +
>> /*
>> * Local Variables:
>> * mode: c
>> diff --git a/lib/jsoninfo/src/olsrd_jsoninfo.h
>> b/lib/jsoninfo/src/olsrd_jsoninfo.h
>> index 8478f62..56acb70 100644
>> --- a/lib/jsoninfo/src/olsrd_jsoninfo.h
>> +++ b/lib/jsoninfo/src/olsrd_jsoninfo.h
>> @@ -62,6 +62,7 @@ extern union olsr_ip_addr jsoninfo_accept_ip;
>> extern union olsr_ip_addr jsoninfo_listen_ip;
>> extern int ipc_port;
>> extern int nompr;
>> +extern bool http_headers;
>>
>> int olsrd_plugin_interface_version(void);
>> int olsrd_plugin_init(void);
>> diff --git a/lib/jsoninfo/src/olsrd_plugin.c
>> b/lib/jsoninfo/src/olsrd_plugin.c
>> index 36550a8..03aa45f 100644
>> --- a/lib/jsoninfo/src/olsrd_plugin.c
>> +++ b/lib/jsoninfo/src/olsrd_plugin.c
>> @@ -64,6 +64,7 @@ union olsr_ip_addr jsoninfo_accept_ip;
>> union olsr_ip_addr jsoninfo_listen_ip;
>> int ipc_port;
>> int nompr;
>> +bool http_headers;
>>
>> static void my_init(void) __attribute__ ((constructor));
>> static void my_fini(void) __attribute__ ((destructor));
>> @@ -79,6 +80,7 @@ my_init(void)
>>
>> /* defaults for parameters */
>> ipc_port = 9090;
>> + http_headers = false;
>> if (olsr_cnf->ip_version == AF_INET) {
>> jsoninfo_accept_ip.v4.s_addr = htonl(INADDR_LOOPBACK);
>> jsoninfo_listen_ip.v4.s_addr = htonl(INADDR_ANY);
>> @@ -120,11 +122,26 @@ store_string(const char *value, void *data,
>> set_plugin_parameter_addon addon __a
>> return 0;
>> }
>>
>> +static int
>> +store_boolean(const char *value, void *data,
>> set_plugin_parameter_addon addon __attribute__ ((unused)))
>> +{
>> + bool *dest = data;
>> + if(strcmp(value, "yes") == 0)
>> + *dest = true;
>> + else if (strcmp(value, "no") == 0)
>> + *dest = false;
>> + else
>> + return 1; //error
>> +
>> + return 0;
>> +}
>> +
>> static const struct olsrd_plugin_parameters plugin_parameters[] = {
>> {.name = "port",.set_plugin_parameter = &set_plugin_port,.data =
>> &ipc_port},
>> {.name = "accept",.set_plugin_parameter =
>> &set_plugin_ipaddress,.data = &jsoninfo_accept_ip},
>> {.name = "listen",.set_plugin_parameter =
>> &set_plugin_ipaddress,.data = &jsoninfo_listen_ip},
>> {.name = "uuidfile",.set_plugin_parameter = &store_string,.data =
>> uuidfile},
>> + {.name = "httpheaders",.set_plugin_parameter = &store_boolean,.data
>> = &http_headers},
>> };
>>
>> void
>>
>
--
Ferry Huberts
More information about the Olsr-dev
mailing list