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:
Joris Vink 2013-11-09 16:21:52 +01:00
parent c80e1d3767
commit 34c2f31a93
8 changed files with 207 additions and 1 deletions

View File

@ -5,7 +5,7 @@ BIN=kore
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/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)
CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes

View File

@ -194,6 +194,19 @@ struct 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_INCREMENT KORE_BUF_INITIAL
@ -333,11 +346,17 @@ void kore_module_load(char *);
void kore_module_reload(void);
int kore_module_loaded(void);
void kore_domain_closelogs(void);
void *kore_module_getsym(char *);
void kore_domain_sslstart(struct kore_domain *);
int kore_module_handler_new(char *, char *, char *, int);
struct kore_domain *kore_domain_lookup(const 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 kore_debug_internal(char *, int, const char *, ...);

View File

@ -53,6 +53,12 @@ workers 4
# Specifies what module to be loaded.
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.
#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 /upload serve_file_upload
static /lock-test serve_lock_test
static /validator serve_validator
}
#domain domain.com {

View File

@ -26,8 +26,10 @@ int serve_b64test(struct http_request *);
int serve_spdyreset(struct http_request *);
int serve_file_upload(struct http_request *);
int serve_lock_test(struct http_request *);
int serve_validator(struct http_request *);
void my_callback(void);
int v_example_func(char *);
void test_base64(u_int8_t *, u_int32_t, struct kore_buf *);
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");
}
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
my_callback(void)
{
@ -212,3 +235,14 @@ my_callback(void)
else
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);
}

View File

@ -46,6 +46,7 @@ static int configure_http_header_max(char **);
static int configure_http_postbody_max(char **);
static int configure_http_hsts_enable(char **);
static int configure_http_keepalive_time(char **);
static int configure_validator(char **);
static void domain_sslstart(void);
static struct {
@ -77,6 +78,7 @@ static struct {
{ "http_postbody_max", configure_http_postbody_max },
{ "http_hsts_enable", configure_http_hsts_enable },
{ "http_keepalive_time", configure_http_keepalive_time },
{ "validator", configure_validator },
{ NULL, NULL },
};
@ -599,6 +601,31 @@ configure_http_keepalive_time(char **argv)
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
domain_sslstart(void)
{

View File

@ -87,6 +87,7 @@ main(int argc, char *argv[])
kore_log_init();
kore_mem_init();
kore_domain_init();
kore_validator_init();
kore_server_sslstart();
kore_parse_config();

View File

@ -86,6 +86,8 @@ kore_module_reload(void)
}
}
kore_validator_reload();
if (kore_module_onload != NULL) {
onload = dlsym(mod_handle, kore_module_onload);
if (onload == NULL)
@ -169,3 +171,9 @@ kore_module_handler_find(char *domain, char *path)
return (NULL);
}
void *
kore_module_getsym(char *symbol)
{
return (dlsym(mod_handle, symbol));
}

110
src/validator.c Normal file
View File

@ -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);
}
}