mirror of https://git.kore.io/kore.git
Add validators to kore, specified in the configuration using 'validator' keyword.
Example: validator v_id function v_id_function validator v_url regex ^/url/path/[a-z]*$ You can then call these using kore_validator_run(char *, char *), example: if (!kore_validator_run("v_url", req->path)) [req->path is bad];
This commit is contained in:
parent
c80e1d3767
commit
34c2f31a93
2
Makefile
2
Makefile
|
@ -5,7 +5,7 @@ BIN=kore
|
||||||
|
|
||||||
S_SRC+= src/kore.c src/accesslog.c src/buf.c src/config.c src/connection.c \
|
S_SRC+= src/kore.c src/accesslog.c src/buf.c src/config.c src/connection.c \
|
||||||
src/domain.c src/http.c src/mem.c src/module.c src/net.c src/pool.c \
|
src/domain.c src/http.c src/mem.c src/module.c src/net.c src/pool.c \
|
||||||
src/spdy.c src/utils.c src/worker.c src/zlib_dict.c
|
src/spdy.c src/validator.c src/utils.c src/worker.c src/zlib_dict.c
|
||||||
S_OBJS= $(S_SRC:.c=.o)
|
S_OBJS= $(S_SRC:.c=.o)
|
||||||
|
|
||||||
CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes
|
CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes
|
||||||
|
|
|
@ -194,6 +194,19 @@ struct kore_domain {
|
||||||
|
|
||||||
TAILQ_HEAD(kore_domain_h, kore_domain);
|
TAILQ_HEAD(kore_domain_h, kore_domain);
|
||||||
|
|
||||||
|
#define KORE_VALIDATOR_TYPE_REGEX 1
|
||||||
|
#define KORE_VALIDATOR_TYPE_FUNCTION 2
|
||||||
|
|
||||||
|
struct kore_validator {
|
||||||
|
u_int8_t type;
|
||||||
|
char *name;
|
||||||
|
char *arg;
|
||||||
|
regex_t rctx;
|
||||||
|
int (*func)(char *);
|
||||||
|
|
||||||
|
TAILQ_ENTRY(kore_validator) list;
|
||||||
|
};
|
||||||
|
|
||||||
#define KORE_BUF_INITIAL 128
|
#define KORE_BUF_INITIAL 128
|
||||||
#define KORE_BUF_INCREMENT KORE_BUF_INITIAL
|
#define KORE_BUF_INCREMENT KORE_BUF_INITIAL
|
||||||
|
|
||||||
|
@ -333,11 +346,17 @@ void kore_module_load(char *);
|
||||||
void kore_module_reload(void);
|
void kore_module_reload(void);
|
||||||
int kore_module_loaded(void);
|
int kore_module_loaded(void);
|
||||||
void kore_domain_closelogs(void);
|
void kore_domain_closelogs(void);
|
||||||
|
void *kore_module_getsym(char *);
|
||||||
void kore_domain_sslstart(struct kore_domain *);
|
void kore_domain_sslstart(struct kore_domain *);
|
||||||
int kore_module_handler_new(char *, char *, char *, int);
|
int kore_module_handler_new(char *, char *, char *, int);
|
||||||
struct kore_domain *kore_domain_lookup(const char *);
|
struct kore_domain *kore_domain_lookup(const char *);
|
||||||
struct kore_module_handle *kore_module_handler_find(char *, char *);
|
struct kore_module_handle *kore_module_handler_find(char *, char *);
|
||||||
|
|
||||||
|
void kore_validator_init(void);
|
||||||
|
void kore_validator_reload(void);
|
||||||
|
int kore_validator_add(char *, u_int8_t, char *);
|
||||||
|
int kore_validator_run(char *, char *);
|
||||||
|
|
||||||
void fatal(const char *, ...);
|
void fatal(const char *, ...);
|
||||||
void kore_debug_internal(char *, int, const char *, ...);
|
void kore_debug_internal(char *, int, const char *, ...);
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,12 @@ workers 4
|
||||||
# Specifies what module to be loaded.
|
# Specifies what module to be loaded.
|
||||||
load modules/example/example.module
|
load modules/example/example.module
|
||||||
|
|
||||||
|
# Validators
|
||||||
|
# validator name type regex|function
|
||||||
|
#
|
||||||
|
validator v_example function v_example_func
|
||||||
|
validator v_regex regex ^/test/[a-z]*$
|
||||||
|
|
||||||
# Specify the SSL ciphers that will be used.
|
# Specify the SSL ciphers that will be used.
|
||||||
#ssl_cipher ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK
|
#ssl_cipher ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK
|
||||||
|
|
||||||
|
@ -98,6 +104,7 @@ domain localhost {
|
||||||
static /spdy-reset serve_spdyreset
|
static /spdy-reset serve_spdyreset
|
||||||
static /upload serve_file_upload
|
static /upload serve_file_upload
|
||||||
static /lock-test serve_lock_test
|
static /lock-test serve_lock_test
|
||||||
|
static /validator serve_validator
|
||||||
}
|
}
|
||||||
|
|
||||||
#domain domain.com {
|
#domain domain.com {
|
||||||
|
|
|
@ -26,8 +26,10 @@ int serve_b64test(struct http_request *);
|
||||||
int serve_spdyreset(struct http_request *);
|
int serve_spdyreset(struct http_request *);
|
||||||
int serve_file_upload(struct http_request *);
|
int serve_file_upload(struct http_request *);
|
||||||
int serve_lock_test(struct http_request *);
|
int serve_lock_test(struct http_request *);
|
||||||
|
int serve_validator(struct http_request *);
|
||||||
|
|
||||||
void my_callback(void);
|
void my_callback(void);
|
||||||
|
int v_example_func(char *);
|
||||||
void test_base64(u_int8_t *, u_int32_t, struct kore_buf *);
|
void test_base64(u_int8_t *, u_int32_t, struct kore_buf *);
|
||||||
|
|
||||||
char *b64tests[] = {
|
char *b64tests[] = {
|
||||||
|
@ -204,6 +206,27 @@ test_base64(u_int8_t *src, u_int32_t slen, struct kore_buf *res)
|
||||||
kore_buf_appendf(res, "\n");
|
kore_buf_appendf(res, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
serve_validator(struct http_request *req)
|
||||||
|
{
|
||||||
|
if (kore_validator_run("v_example", "test"))
|
||||||
|
kore_log(LOG_NOTICE, "v_example ok (expected)");
|
||||||
|
else
|
||||||
|
kore_log(LOG_NOTICE, "v_example failed");
|
||||||
|
|
||||||
|
if (kore_validator_run("v_regex", "/test/123"))
|
||||||
|
kore_log(LOG_NOTICE, "regex #1 ok");
|
||||||
|
else
|
||||||
|
kore_log(LOG_NOTICE, "regex #1 failed (expected)");
|
||||||
|
|
||||||
|
if (kore_validator_run("v_regex", "/test/joris"))
|
||||||
|
kore_log(LOG_NOTICE, "regex #2 ok (expected)");
|
||||||
|
else
|
||||||
|
kore_log(LOG_NOTICE, "regex #2 failed");
|
||||||
|
|
||||||
|
return (http_response(req, 200, (u_int8_t *)"OK", 2));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
my_callback(void)
|
my_callback(void)
|
||||||
{
|
{
|
||||||
|
@ -212,3 +235,14 @@ my_callback(void)
|
||||||
else
|
else
|
||||||
kore_log(LOG_NOTICE, "running from parent");
|
kore_log(LOG_NOTICE, "running from parent");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
v_example_func(char *data)
|
||||||
|
{
|
||||||
|
kore_log(LOG_NOTICE, "v_example_func called");
|
||||||
|
|
||||||
|
if (!strcmp(data, "test"))
|
||||||
|
return (KORE_RESULT_OK);
|
||||||
|
|
||||||
|
return (KORE_RESULT_ERROR);
|
||||||
|
}
|
||||||
|
|
27
src/config.c
27
src/config.c
|
@ -46,6 +46,7 @@ static int configure_http_header_max(char **);
|
||||||
static int configure_http_postbody_max(char **);
|
static int configure_http_postbody_max(char **);
|
||||||
static int configure_http_hsts_enable(char **);
|
static int configure_http_hsts_enable(char **);
|
||||||
static int configure_http_keepalive_time(char **);
|
static int configure_http_keepalive_time(char **);
|
||||||
|
static int configure_validator(char **);
|
||||||
static void domain_sslstart(void);
|
static void domain_sslstart(void);
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
|
@ -77,6 +78,7 @@ static struct {
|
||||||
{ "http_postbody_max", configure_http_postbody_max },
|
{ "http_postbody_max", configure_http_postbody_max },
|
||||||
{ "http_hsts_enable", configure_http_hsts_enable },
|
{ "http_hsts_enable", configure_http_hsts_enable },
|
||||||
{ "http_keepalive_time", configure_http_keepalive_time },
|
{ "http_keepalive_time", configure_http_keepalive_time },
|
||||||
|
{ "validator", configure_validator },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -599,6 +601,31 @@ configure_http_keepalive_time(char **argv)
|
||||||
return (KORE_RESULT_OK);
|
return (KORE_RESULT_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
configure_validator(char **argv)
|
||||||
|
{
|
||||||
|
u_int8_t type;
|
||||||
|
|
||||||
|
if (argv[3] == NULL)
|
||||||
|
return (KORE_RESULT_ERROR);
|
||||||
|
|
||||||
|
if (!strcmp(argv[2], "regex")) {
|
||||||
|
type = KORE_VALIDATOR_TYPE_REGEX;
|
||||||
|
} else if (!strcmp(argv[2], "function")) {
|
||||||
|
type = KORE_VALIDATOR_TYPE_FUNCTION;
|
||||||
|
} else {
|
||||||
|
printf("bad type for validator %s\n", argv[1]);
|
||||||
|
return (KORE_RESULT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kore_validator_add(argv[1], type, argv[3])) {
|
||||||
|
printf("bad validator specified: %s\n", argv[1]);
|
||||||
|
return (KORE_RESULT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (KORE_RESULT_OK);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
domain_sslstart(void)
|
domain_sslstart(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -87,6 +87,7 @@ main(int argc, char *argv[])
|
||||||
kore_log_init();
|
kore_log_init();
|
||||||
kore_mem_init();
|
kore_mem_init();
|
||||||
kore_domain_init();
|
kore_domain_init();
|
||||||
|
kore_validator_init();
|
||||||
kore_server_sslstart();
|
kore_server_sslstart();
|
||||||
kore_parse_config();
|
kore_parse_config();
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,8 @@ kore_module_reload(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kore_validator_reload();
|
||||||
|
|
||||||
if (kore_module_onload != NULL) {
|
if (kore_module_onload != NULL) {
|
||||||
onload = dlsym(mod_handle, kore_module_onload);
|
onload = dlsym(mod_handle, kore_module_onload);
|
||||||
if (onload == NULL)
|
if (onload == NULL)
|
||||||
|
@ -169,3 +171,9 @@ kore_module_handler_find(char *domain, char *path)
|
||||||
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
kore_module_getsym(char *symbol)
|
||||||
|
{
|
||||||
|
return (dlsym(mod_handle, symbol));
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* 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 "kore.h"
|
||||||
|
|
||||||
|
TAILQ_HEAD(, kore_validator) validators;
|
||||||
|
|
||||||
|
void
|
||||||
|
kore_validator_init(void)
|
||||||
|
{
|
||||||
|
TAILQ_INIT(&validators);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kore_validator_add(char *name, u_int8_t type, char *arg)
|
||||||
|
{
|
||||||
|
struct kore_validator *val;
|
||||||
|
|
||||||
|
val = kore_malloc(sizeof(*val));
|
||||||
|
val->type = type;
|
||||||
|
|
||||||
|
switch (val->type) {
|
||||||
|
case KORE_VALIDATOR_TYPE_REGEX:
|
||||||
|
if (regcomp(&(val->rctx), arg, REG_NOSUB)) {
|
||||||
|
kore_mem_free(val);
|
||||||
|
kore_log(LOG_NOTICE,
|
||||||
|
"validator %s has bad regex %s", name, arg);
|
||||||
|
return (KORE_RESULT_ERROR);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KORE_VALIDATOR_TYPE_FUNCTION:
|
||||||
|
if ((val->func = kore_module_getsym(arg)) == NULL) {
|
||||||
|
kore_mem_free(val);
|
||||||
|
kore_log(LOG_NOTICE,
|
||||||
|
"validator %s has undefined callback %s",
|
||||||
|
name, arg);
|
||||||
|
return (KORE_RESULT_ERROR);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
kore_mem_free(val);
|
||||||
|
return (KORE_RESULT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
val->arg = kore_strdup(arg);
|
||||||
|
val->name = kore_strdup(name);
|
||||||
|
TAILQ_INSERT_TAIL(&validators, val, list);
|
||||||
|
|
||||||
|
return (KORE_RESULT_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kore_validator_run(char *name, char *data)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
struct kore_validator *val;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(val, &validators, list) {
|
||||||
|
if (strcmp(val->name, name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (val->type) {
|
||||||
|
case KORE_VALIDATOR_TYPE_REGEX:
|
||||||
|
if (!regexec(&(val->rctx), data, 0, NULL, 0))
|
||||||
|
r = KORE_RESULT_OK;
|
||||||
|
else
|
||||||
|
r = KORE_RESULT_ERROR;
|
||||||
|
break;
|
||||||
|
case KORE_VALIDATOR_TYPE_FUNCTION:
|
||||||
|
r = val->func(data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r = KORE_RESULT_ERROR;
|
||||||
|
kore_log(LOG_NOTICE, "invalid type %d for validator %s",
|
||||||
|
val->type, val->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (r);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (KORE_RESULT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
kore_validator_reload(void)
|
||||||
|
{
|
||||||
|
struct kore_validator *val;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(val, &validators, list) {
|
||||||
|
if (val->type != KORE_VALIDATOR_TYPE_FUNCTION)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((val->func = kore_module_getsym(val->arg)) == NULL)
|
||||||
|
fatal("no function for validator %s found", val->name);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue