2013-04-17 22:34:27 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2013 Joris Vink <joris@coders.se>
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/queue.h>
|
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
2013-04-21 20:21:46 +02:00
|
|
|
#include <openssl/err.h>
|
|
|
|
#include <openssl/ssl.h>
|
|
|
|
|
2013-04-17 22:34:27 +02:00
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
2013-04-21 20:21:46 +02:00
|
|
|
#include <stdarg.h>
|
2013-04-17 22:34:27 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2013-05-29 14:29:46 +02:00
|
|
|
#include <regex.h>
|
2013-05-01 12:23:21 +02:00
|
|
|
#include <zlib.h>
|
2013-04-17 22:34:27 +02:00
|
|
|
|
2013-04-28 19:11:44 +02:00
|
|
|
#include "spdy.h"
|
2013-04-17 22:34:27 +02:00
|
|
|
#include "kore.h"
|
|
|
|
|
2013-05-01 20:10:45 +02:00
|
|
|
static struct {
|
|
|
|
char *name;
|
|
|
|
int value;
|
|
|
|
} month_names[] = {
|
|
|
|
{ "Jan", 0 },
|
|
|
|
{ "Feb", 1 },
|
|
|
|
{ "Mar", 2 },
|
|
|
|
{ "Apr", 3 },
|
|
|
|
{ "May", 4 },
|
|
|
|
{ "Jun", 5 },
|
|
|
|
{ "Jul", 6 },
|
|
|
|
{ "Aug", 7 },
|
|
|
|
{ "Sep", 8 },
|
|
|
|
{ "Oct", 9 },
|
|
|
|
{ "Nov", 10 },
|
|
|
|
{ "Dec", 11 },
|
|
|
|
{ NULL, 0 },
|
|
|
|
};
|
|
|
|
|
2013-04-17 22:34:27 +02:00
|
|
|
void *
|
|
|
|
kore_malloc(size_t len)
|
|
|
|
{
|
|
|
|
void *ptr;
|
|
|
|
|
|
|
|
if ((ptr = malloc(len)) == NULL)
|
|
|
|
fatal("kore_malloc(%d): %d", len, errno);
|
|
|
|
|
2013-05-02 03:51:04 +02:00
|
|
|
memset(ptr, 0, len);
|
2013-04-17 22:34:27 +02:00
|
|
|
return (ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
kore_realloc(void *ptr, size_t len)
|
|
|
|
{
|
|
|
|
void *nptr;
|
|
|
|
|
|
|
|
if ((nptr = realloc(ptr, len)) == NULL)
|
|
|
|
fatal("kore_realloc(%p, %d): %d", ptr, len, errno);
|
|
|
|
|
2013-04-28 23:42:13 +02:00
|
|
|
return (nptr);
|
2013-04-17 22:34:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
kore_calloc(size_t memb, size_t len)
|
|
|
|
{
|
|
|
|
void *ptr;
|
|
|
|
|
|
|
|
if ((ptr = calloc(memb, len)) == NULL)
|
|
|
|
fatal("kore_calloc(%d, %d): %d", memb, len, errno);
|
|
|
|
|
2013-05-02 03:51:04 +02:00
|
|
|
memset(ptr, 0, memb * len);
|
2013-04-17 22:34:27 +02:00
|
|
|
return (ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
kore_strdup(const char *str)
|
|
|
|
{
|
|
|
|
char *nstr;
|
|
|
|
|
|
|
|
if ((nstr = strdup(str)) == NULL)
|
|
|
|
fatal("kore_strdup(): %d", errno);
|
|
|
|
|
|
|
|
return (nstr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
kore_log_internal(char *file, int line, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
char buf[2048];
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
vsnprintf(buf, sizeof(buf), fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
|
2013-06-04 11:55:38 +02:00
|
|
|
printf("[%d] %s:%d - %s\n", mypid, file, line, buf);
|
2013-04-17 22:34:27 +02:00
|
|
|
}
|
|
|
|
|
2013-05-01 00:35:33 +02:00
|
|
|
void
|
|
|
|
kore_strlcpy(char *dst, const char *src, size_t len)
|
|
|
|
{
|
|
|
|
char *d = dst;
|
|
|
|
const char *s = src;
|
|
|
|
|
|
|
|
while ((*d++ = *s++) != '\0') {
|
|
|
|
if (d == (dst + len - 1)) {
|
|
|
|
*d = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-01 16:03:48 +02:00
|
|
|
long long
|
|
|
|
kore_strtonum(const char *str, long long min, long long max, int *err)
|
|
|
|
{
|
|
|
|
long long l;
|
|
|
|
char *ep;
|
|
|
|
|
|
|
|
if (min > max) {
|
|
|
|
*err = KORE_RESULT_ERROR;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
l = 0;
|
|
|
|
errno = 0;
|
|
|
|
l = strtoll(str, &ep, 10);
|
|
|
|
if (errno != 0 || str == ep || *ep != '\0') {
|
|
|
|
*err = KORE_RESULT_ERROR;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (l < min) {
|
|
|
|
*err = KORE_RESULT_ERROR;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (l > max) {
|
|
|
|
*err = KORE_RESULT_ERROR;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
*err = KORE_RESULT_OK;
|
|
|
|
return (l);
|
|
|
|
}
|
|
|
|
|
2013-05-01 20:10:45 +02:00
|
|
|
int
|
|
|
|
kore_split_string(char *input, char *delim, char **out, size_t ele)
|
|
|
|
{
|
|
|
|
int count;
|
|
|
|
char **ap;
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
for (ap = out; ap < &out[ele - 1] &&
|
|
|
|
(*ap = strsep(&input, delim)) != NULL;) {
|
|
|
|
if (**ap != '\0') {
|
|
|
|
ap++;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*ap = NULL;
|
|
|
|
return (count);
|
|
|
|
}
|
|
|
|
|
|
|
|
time_t
|
|
|
|
kore_date_to_time(char *http_date)
|
|
|
|
{
|
|
|
|
time_t t;
|
|
|
|
int err, i;
|
|
|
|
struct tm tm, *gtm;
|
|
|
|
char *args[7], *tbuf[5], *sdup;
|
|
|
|
|
|
|
|
time(&t);
|
|
|
|
gtm = gmtime(&t);
|
|
|
|
sdup = kore_strdup(http_date);
|
|
|
|
|
|
|
|
t = KORE_RESULT_ERROR;
|
|
|
|
|
|
|
|
if (kore_split_string(sdup, " ", args, 7) != 6) {
|
|
|
|
kore_log("misformed http-date: '%s'", http_date);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
tm.tm_year = kore_strtonum(args[3], 2013, 2068, &err) - 1900;
|
|
|
|
if (err == KORE_RESULT_ERROR || tm.tm_year < gtm->tm_year) {
|
|
|
|
kore_log("misformed year in http-date: '%s'", http_date);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; month_names[i].name != NULL; i++) {
|
|
|
|
if (!strcmp(month_names[i].name, args[2])) {
|
|
|
|
tm.tm_mon = month_names[i].value;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (month_names[i].name == NULL) {
|
|
|
|
kore_log("misformed month in http-date: '%s'", http_date);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
tm.tm_mday = kore_strtonum(args[1], 1, 31, &err);
|
|
|
|
if (err == KORE_RESULT_ERROR) {
|
|
|
|
kore_log("misformed mday in http-date: '%s'", http_date);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kore_split_string(args[4], ":", tbuf, 5) != 3) {
|
|
|
|
kore_log("misformed HH:MM:SS in http-date: '%s'", http_date);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
tm.tm_hour = kore_strtonum(tbuf[0], 1, 23, &err);
|
|
|
|
if (err == KORE_RESULT_ERROR) {
|
|
|
|
kore_log("misformed hour in http-date: '%s'", http_date);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
tm.tm_min = kore_strtonum(tbuf[1], 1, 59, &err);
|
|
|
|
if (err == KORE_RESULT_ERROR) {
|
|
|
|
kore_log("misformed minutes in http-date: '%s'", http_date);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
tm.tm_sec = kore_strtonum(tbuf[2], 0, 60, &err);
|
|
|
|
if (err == KORE_RESULT_ERROR) {
|
|
|
|
kore_log("misformed seconds in http-date: '%s'", http_date);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
t = mktime(&tm);
|
|
|
|
if (t == -1) {
|
|
|
|
t = 0;
|
|
|
|
kore_log("mktime() on '%s' failed", http_date);
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
free(sdup);
|
|
|
|
return (t);
|
|
|
|
}
|
|
|
|
|
2013-05-01 21:16:09 +02:00
|
|
|
char *
|
|
|
|
kore_time_to_date(time_t now)
|
|
|
|
{
|
|
|
|
struct tm *tm;
|
|
|
|
static time_t last = 0;
|
|
|
|
static char tbuf[32];
|
|
|
|
|
|
|
|
if (now != last) {
|
|
|
|
last = now;
|
|
|
|
|
|
|
|
tm = gmtime(&now);
|
|
|
|
if (!strftime(tbuf, sizeof(tbuf), "%a, %d %b %Y %T GMT", tm)) {
|
|
|
|
kore_log("strftime() gave us NULL (%ld)", now);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (tbuf);
|
|
|
|
}
|
|
|
|
|
2013-04-17 22:34:27 +02:00
|
|
|
void
|
|
|
|
fatal(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
char buf[2048];
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
vsnprintf(buf, sizeof(buf), fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
printf("error: %s\n", buf);
|
|
|
|
exit(1);
|
|
|
|
}
|