2013-05-01 17:17:16 +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.
|
|
|
|
*/
|
|
|
|
|
2014-03-07 09:55:28 +01:00
|
|
|
#include <sys/stat.h>
|
|
|
|
|
2013-05-01 17:17:16 +02:00
|
|
|
#include <ctype.h>
|
2013-09-02 08:52:16 +02:00
|
|
|
#include <limits.h>
|
2013-05-01 17:17:16 +02:00
|
|
|
#include <fcntl.h>
|
2013-06-26 11:18:32 +02:00
|
|
|
#include <pwd.h>
|
2013-05-01 17:17:16 +02:00
|
|
|
|
|
|
|
#include "kore.h"
|
2013-09-22 20:05:24 +02:00
|
|
|
#include "http.h"
|
2013-05-01 17:17:16 +02:00
|
|
|
|
2014-07-04 09:14:05 +02:00
|
|
|
#if defined(KORE_USE_PGSQL)
|
|
|
|
#include "pgsql.h"
|
|
|
|
#endif
|
|
|
|
|
2014-01-22 22:55:10 +01:00
|
|
|
/* XXX - This is becoming a clusterfuck. Fix it. */
|
|
|
|
|
2014-04-22 13:15:19 +02:00
|
|
|
static int configure_include(char **);
|
2013-06-04 16:53:30 +02:00
|
|
|
static int configure_bind(char **);
|
|
|
|
static int configure_load(char **);
|
|
|
|
static int configure_handler(char **);
|
|
|
|
static int configure_domain(char **);
|
|
|
|
static int configure_chroot(char **);
|
|
|
|
static int configure_runas(char **);
|
|
|
|
static int configure_workers(char **);
|
|
|
|
static int configure_pidfile(char **);
|
2013-06-24 11:32:45 +02:00
|
|
|
static int configure_accesslog(char **);
|
2013-06-05 09:47:08 +02:00
|
|
|
static int configure_certfile(char **);
|
|
|
|
static int configure_certkey(char **);
|
2014-07-31 09:14:03 +02:00
|
|
|
static int configure_rlimit_nofiles(char **);
|
2013-06-26 16:37:22 +02:00
|
|
|
static int configure_max_connections(char **);
|
2013-06-27 08:43:07 +02:00
|
|
|
static int configure_ssl_cipher(char **);
|
2013-08-07 16:51:39 +02:00
|
|
|
static int configure_ssl_dhparam(char **);
|
2013-08-07 16:59:45 +02:00
|
|
|
static int configure_ssl_no_compression(char **);
|
2013-07-13 20:19:01 +02:00
|
|
|
static int configure_spdy_idle_time(char **);
|
2013-09-22 20:05:24 +02:00
|
|
|
static int configure_http_header_max(char **);
|
2014-10-08 11:03:14 +02:00
|
|
|
static int configure_http_body_max(char **);
|
2013-10-15 10:44:56 +02:00
|
|
|
static int configure_http_hsts_enable(char **);
|
2013-10-15 11:10:45 +02:00
|
|
|
static int configure_http_keepalive_time(char **);
|
2013-11-09 16:21:52 +01:00
|
|
|
static int configure_validator(char **);
|
2013-11-10 15:17:15 +01:00
|
|
|
static int configure_params(char **);
|
|
|
|
static int configure_validate(char **);
|
2013-12-14 16:31:07 +01:00
|
|
|
static int configure_require_client_cert(char **);
|
2014-01-22 22:55:10 +01:00
|
|
|
static int configure_authentication(char **);
|
|
|
|
static int configure_authentication_uri(char **);
|
|
|
|
static int configure_authentication_type(char **);
|
|
|
|
static int configure_authentication_value(char **);
|
|
|
|
static int configure_authentication_validator(char **);
|
|
|
|
|
2014-07-04 09:14:05 +02:00
|
|
|
#if defined(KORE_USE_PGSQL)
|
|
|
|
static int configure_pgsql_conn_max(char **);
|
|
|
|
#endif
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
static void domain_sslstart(void);
|
2014-04-22 13:15:19 +02:00
|
|
|
static void kore_parse_config_file(char *);
|
2013-05-01 17:17:16 +02:00
|
|
|
|
|
|
|
static struct {
|
|
|
|
const char *name;
|
|
|
|
int (*configure)(char **);
|
|
|
|
} config_names[] = {
|
2014-04-22 13:15:19 +02:00
|
|
|
{ "include", configure_include },
|
2013-06-26 16:37:22 +02:00
|
|
|
{ "bind", configure_bind },
|
|
|
|
{ "load", configure_load },
|
|
|
|
{ "static", configure_handler },
|
|
|
|
{ "dynamic", configure_handler },
|
2013-06-27 08:43:07 +02:00
|
|
|
{ "ssl_cipher", configure_ssl_cipher },
|
2013-08-07 16:51:39 +02:00
|
|
|
{ "ssl_dhparam", configure_ssl_dhparam },
|
2013-08-07 16:59:45 +02:00
|
|
|
{ "ssl_no_compression", configure_ssl_no_compression },
|
2013-07-13 20:19:01 +02:00
|
|
|
{ "spdy_idle_time", configure_spdy_idle_time },
|
2013-06-26 16:37:22 +02:00
|
|
|
{ "domain", configure_domain },
|
|
|
|
{ "chroot", configure_chroot },
|
|
|
|
{ "runas", configure_runas },
|
|
|
|
{ "workers", configure_workers },
|
|
|
|
{ "worker_max_connections", configure_max_connections },
|
2014-07-31 09:14:03 +02:00
|
|
|
{ "worker_rlimit_nofiles", configure_rlimit_nofiles },
|
2013-06-26 16:37:22 +02:00
|
|
|
{ "pidfile", configure_pidfile },
|
|
|
|
{ "accesslog", configure_accesslog },
|
|
|
|
{ "certfile", configure_certfile },
|
|
|
|
{ "certkey", configure_certkey },
|
2013-12-14 16:31:07 +01:00
|
|
|
{ "require_client_cert", configure_require_client_cert },
|
2013-09-22 20:05:24 +02:00
|
|
|
{ "http_header_max", configure_http_header_max },
|
2014-10-08 11:03:14 +02:00
|
|
|
{ "http_body_max", configure_http_body_max },
|
2013-10-15 10:44:56 +02:00
|
|
|
{ "http_hsts_enable", configure_http_hsts_enable },
|
2013-10-15 11:10:45 +02:00
|
|
|
{ "http_keepalive_time", configure_http_keepalive_time },
|
2013-11-09 16:21:52 +01:00
|
|
|
{ "validator", configure_validator },
|
2013-11-10 15:17:15 +01:00
|
|
|
{ "params", configure_params },
|
|
|
|
{ "validate", configure_validate },
|
2014-01-22 22:55:10 +01:00
|
|
|
{ "authentication", configure_authentication },
|
|
|
|
{ "authentication_uri", configure_authentication_uri },
|
|
|
|
{ "authentication_type", configure_authentication_type },
|
|
|
|
{ "authentication_value", configure_authentication_value },
|
|
|
|
{ "authentication_validator", configure_authentication_validator },
|
2014-07-04 09:14:05 +02:00
|
|
|
#if defined(KORE_USE_PGSQL)
|
|
|
|
{ "pgsql_conn_max", configure_pgsql_conn_max },
|
|
|
|
#endif
|
2013-06-26 16:37:22 +02:00
|
|
|
{ NULL, NULL },
|
2013-05-01 17:17:16 +02:00
|
|
|
};
|
|
|
|
|
2013-11-10 15:17:15 +01:00
|
|
|
char *config_file = NULL;
|
|
|
|
static u_int8_t current_method = 0;
|
2014-01-22 22:55:10 +01:00
|
|
|
static struct kore_auth *current_auth = NULL;
|
2013-11-10 15:17:15 +01:00
|
|
|
static struct kore_domain *current_domain = NULL;
|
|
|
|
static struct kore_module_handle *current_handler = NULL;
|
2013-05-02 13:30:13 +02:00
|
|
|
|
2013-05-01 17:17:16 +02:00
|
|
|
void
|
2013-06-26 11:18:32 +02:00
|
|
|
kore_parse_config(void)
|
2014-04-22 13:15:19 +02:00
|
|
|
{
|
2014-07-31 13:59:42 +02:00
|
|
|
char *p;
|
|
|
|
|
2014-04-22 13:15:19 +02:00
|
|
|
kore_parse_config_file(config_file);
|
|
|
|
|
|
|
|
if (!kore_module_loaded())
|
|
|
|
fatal("no site module was loaded");
|
2014-07-31 13:59:42 +02:00
|
|
|
|
2014-04-22 13:15:19 +02:00
|
|
|
if (LIST_EMPTY(&listeners))
|
|
|
|
fatal("no listeners defined");
|
2014-07-31 13:59:42 +02:00
|
|
|
|
|
|
|
if (skip_chroot != 1 && chroot_path == NULL)
|
2014-04-22 13:15:19 +02:00
|
|
|
fatal("missing a chroot path");
|
2014-07-31 13:59:42 +02:00
|
|
|
|
|
|
|
if (runas_user == NULL) {
|
|
|
|
if ((p = getlogin()) == NULL)
|
|
|
|
fatal("missing a username to run as");
|
|
|
|
|
|
|
|
/* runas_user is free'd later down the line. */
|
|
|
|
runas_user = kore_strdup(p);
|
|
|
|
}
|
|
|
|
|
2014-04-22 13:15:19 +02:00
|
|
|
if ((pw = getpwnam(runas_user)) == NULL)
|
|
|
|
fatal("user '%s' does not exist", runas_user);
|
|
|
|
|
|
|
|
if (getuid() != 0 && skip_chroot == 0)
|
|
|
|
fatal("Cannot chroot(), use -n to skip it");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
kore_parse_config_file(char *fpath)
|
2013-05-01 17:17:16 +02:00
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
int i, lineno;
|
2013-05-01 20:10:45 +02:00
|
|
|
char buf[BUFSIZ], *p, *t, *argv[5];
|
2013-05-01 17:17:16 +02:00
|
|
|
|
2014-04-22 13:15:19 +02:00
|
|
|
if ((fp = fopen(fpath, "r")) == NULL)
|
|
|
|
fatal("configuration given cannot be opened: %s", fpath);
|
2013-06-26 11:18:32 +02:00
|
|
|
|
2014-04-22 13:15:19 +02:00
|
|
|
kore_debug("parsing configuration file '%s'", fpath);
|
2013-05-01 17:17:16 +02:00
|
|
|
|
|
|
|
lineno = 1;
|
|
|
|
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
|
|
|
p = buf;
|
|
|
|
buf[strcspn(buf, "\n")] = '\0';
|
|
|
|
|
|
|
|
while (isspace(*p))
|
|
|
|
p++;
|
|
|
|
if (p[0] == '#' || p[0] == '\0') {
|
|
|
|
lineno++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (t = p; *t != '\0'; t++) {
|
|
|
|
if (*t == '\t')
|
|
|
|
*t = ' ';
|
|
|
|
}
|
|
|
|
|
2013-11-10 15:17:15 +01:00
|
|
|
if (!strcmp(p, "}") && current_handler != NULL) {
|
|
|
|
lineno++;
|
|
|
|
current_handler = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-01-22 22:55:10 +01:00
|
|
|
if (!strcmp(p, "}") && current_auth != NULL) {
|
|
|
|
if (current_auth->validator == NULL) {
|
|
|
|
fatal("no authentication validator for %s",
|
|
|
|
current_auth->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
lineno++;
|
|
|
|
current_auth = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
if (!strcmp(p, "}") && current_domain != NULL)
|
|
|
|
domain_sslstart();
|
|
|
|
|
2013-05-01 20:10:45 +02:00
|
|
|
kore_split_string(p, " ", argv, 5);
|
2013-05-01 17:17:16 +02:00
|
|
|
for (i = 0; config_names[i].name != NULL; i++) {
|
|
|
|
if (!strcmp(config_names[i].name, argv[0])) {
|
|
|
|
if (!config_names[i].configure(argv)) {
|
|
|
|
fatal("configuration error on line %d",
|
|
|
|
lineno);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lineno++;
|
|
|
|
}
|
2013-06-26 11:18:32 +02:00
|
|
|
|
2014-04-09 14:43:23 +02:00
|
|
|
fclose(fp);
|
2014-04-22 13:15:19 +02:00
|
|
|
}
|
2014-04-09 14:43:23 +02:00
|
|
|
|
2014-04-22 13:15:19 +02:00
|
|
|
static int
|
|
|
|
configure_include(char **argv)
|
|
|
|
{
|
|
|
|
if (argv[1] == NULL) {
|
|
|
|
printf("No file given in include directive\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
2013-11-18 00:42:57 +01:00
|
|
|
|
2014-04-22 13:15:19 +02:00
|
|
|
kore_parse_config_file(argv[1]);
|
|
|
|
return (KORE_RESULT_OK);
|
2013-05-01 17:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
configure_bind(char **argv)
|
|
|
|
{
|
|
|
|
if (argv[1] == NULL || argv[2] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
2013-07-27 20:56:15 +02:00
|
|
|
return (kore_server_bind(argv[1], argv[2]));
|
2013-05-01 17:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
configure_load(char **argv)
|
|
|
|
{
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
2013-12-15 01:11:56 +01:00
|
|
|
kore_module_load(argv[1], argv[2]);
|
2013-05-30 21:26:39 +02:00
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-06-27 08:43:07 +02:00
|
|
|
static int
|
|
|
|
configure_ssl_cipher(char **argv)
|
|
|
|
{
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
if (strcmp(kore_ssl_cipher_list, KORE_DEFAULT_CIPHER_LIST)) {
|
|
|
|
kore_debug("duplicate ssl_cipher directive specified");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
kore_ssl_cipher_list = kore_strdup(argv[1]);
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-08-07 16:51:39 +02:00
|
|
|
static int
|
|
|
|
configure_ssl_dhparam(char **argv)
|
|
|
|
{
|
2014-08-01 10:22:32 +02:00
|
|
|
#if !defined(KORE_BENCHMARK)
|
2013-08-07 16:51:39 +02:00
|
|
|
BIO *bio;
|
|
|
|
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
if (ssl_dhparam != NULL) {
|
|
|
|
kore_debug("duplicate ssl_dhparam directive specified");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((bio = BIO_new_file(argv[1], "r")) == NULL) {
|
2013-09-22 20:11:56 +02:00
|
|
|
printf("%s did not exist\n", argv[1]);
|
2013-08-07 16:51:39 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
ssl_dhparam = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
|
|
|
|
BIO_free(bio);
|
|
|
|
|
|
|
|
if (ssl_dhparam == NULL) {
|
2013-09-22 20:11:56 +02:00
|
|
|
printf("PEM_read_bio_DHparams(): %s\n", ssl_errno_s);
|
2013-08-07 16:51:39 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
2014-08-01 10:22:32 +02:00
|
|
|
#endif
|
2013-08-07 16:51:39 +02:00
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-08-07 16:59:45 +02:00
|
|
|
static int
|
|
|
|
configure_ssl_no_compression(char **argv)
|
|
|
|
{
|
2014-08-05 13:07:32 +02:00
|
|
|
printf("ssl_no_compression is deprecated, and always on by default\n");
|
2013-08-07 16:59:45 +02:00
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-07-13 20:19:01 +02:00
|
|
|
static int
|
|
|
|
configure_spdy_idle_time(char **argv)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
2013-08-13 16:13:43 +02:00
|
|
|
spdy_idle_time = kore_strtonum(argv[1], 10, 0, 65535, &err);
|
2013-07-13 20:19:01 +02:00
|
|
|
if (err != KORE_RESULT_OK) {
|
2013-09-22 20:11:56 +02:00
|
|
|
printf("spdy_idle_time has invalid value: %s\n", argv[1]);
|
2013-07-13 20:19:01 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
spdy_idle_time = spdy_idle_time * 1000;
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-05-02 13:30:13 +02:00
|
|
|
static int
|
|
|
|
configure_domain(char **argv)
|
|
|
|
{
|
2013-06-24 11:32:45 +02:00
|
|
|
if (argv[2] == NULL)
|
2013-05-02 13:30:13 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
if (current_domain != NULL) {
|
2013-09-22 20:11:56 +02:00
|
|
|
printf("previous domain configuration not closed\n");
|
2013-06-24 11:32:45 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(argv[2], "{")) {
|
2013-09-22 20:11:56 +02:00
|
|
|
printf("missing { for domain directive\n");
|
2013-06-24 11:32:45 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!kore_domain_new(argv[1])) {
|
2013-09-22 20:11:56 +02:00
|
|
|
printf("could not create new domain %s\n", argv[1]);
|
2013-05-29 14:29:46 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
2013-05-02 13:30:13 +02:00
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
current_domain = kore_domain_lookup(argv[1]);
|
2013-05-02 13:30:13 +02:00
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-05-01 17:17:16 +02:00
|
|
|
static int
|
|
|
|
configure_handler(char **argv)
|
|
|
|
{
|
|
|
|
int type;
|
|
|
|
|
2013-05-02 13:30:13 +02:00
|
|
|
if (current_domain == NULL) {
|
2013-09-22 20:11:56 +02:00
|
|
|
printf("missing domain for page handler\n");
|
2013-05-02 13:30:13 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
2013-05-01 17:17:16 +02:00
|
|
|
if (argv[1] == NULL || argv[2] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
if (!strcmp(argv[0], "static"))
|
|
|
|
type = HANDLER_TYPE_STATIC;
|
|
|
|
else if (!strcmp(argv[0], "dynamic"))
|
|
|
|
type = HANDLER_TYPE_DYNAMIC;
|
|
|
|
else
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
if (!kore_module_handler_new(argv[1],
|
2014-01-22 22:55:10 +01:00
|
|
|
current_domain->domain, argv[2], argv[3], type)) {
|
2013-06-04 16:30:53 +02:00
|
|
|
kore_debug("cannot create handler for %s", argv[1]);
|
2013-05-01 17:17:16 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
2013-05-04 22:18:27 +02:00
|
|
|
|
2013-12-14 16:31:07 +01:00
|
|
|
static int
|
|
|
|
configure_require_client_cert(char **argv)
|
|
|
|
{
|
|
|
|
if (current_domain == NULL) {
|
|
|
|
printf("missing domain page require_client_cert\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv[1] == NULL) {
|
|
|
|
printf("missing argument for require_client_cert\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_domain->cafile != NULL) {
|
|
|
|
printf("require_client_cert already set for %s\n",
|
|
|
|
current_domain->domain);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
current_domain->cafile = kore_strdup(argv[1]);
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-05-04 22:18:27 +02:00
|
|
|
static int
|
|
|
|
configure_chroot(char **argv)
|
|
|
|
{
|
|
|
|
if (chroot_path != NULL) {
|
2013-06-04 16:30:53 +02:00
|
|
|
kore_debug("duplicate chroot path specified");
|
2013-05-04 22:18:27 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
chroot_path = kore_strdup(argv[1]);
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
configure_runas(char **argv)
|
|
|
|
{
|
|
|
|
if (runas_user != NULL) {
|
2013-06-04 16:30:53 +02:00
|
|
|
kore_debug("duplicate runas user specified");
|
2013-05-04 22:18:27 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
runas_user = kore_strdup(argv[1]);
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
2013-05-30 19:36:42 +02:00
|
|
|
|
|
|
|
static int
|
|
|
|
configure_workers(char **argv)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (worker_count != 0) {
|
2013-06-04 16:30:53 +02:00
|
|
|
kore_debug("duplicate worker directive specified");
|
2013-05-30 19:36:42 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
2013-08-13 16:13:43 +02:00
|
|
|
worker_count = kore_strtonum(argv[1], 10, 1, 255, &err);
|
2013-05-30 19:36:42 +02:00
|
|
|
if (err != KORE_RESULT_OK) {
|
2013-09-22 20:11:56 +02:00
|
|
|
printf("%s is not a correct worker number\n", argv[1]);
|
2013-05-30 19:36:42 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
2013-06-04 16:53:30 +02:00
|
|
|
|
|
|
|
static int
|
|
|
|
configure_pidfile(char **argv)
|
|
|
|
{
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
if (strcmp(kore_pidfile, KORE_PIDFILE_DEFAULT)) {
|
|
|
|
kore_debug("duplicate pidfile directive specified");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
kore_pidfile = kore_strdup(argv[1]);
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
2013-06-05 09:47:08 +02:00
|
|
|
|
|
|
|
static int
|
2013-06-24 11:32:45 +02:00
|
|
|
configure_accesslog(char **argv)
|
2013-06-05 09:47:08 +02:00
|
|
|
{
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
if (current_domain == NULL) {
|
|
|
|
kore_debug("missing domain for accesslog");
|
2013-06-05 09:47:08 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
if (current_domain->accesslog != -1) {
|
|
|
|
kore_debug("domain %s already has an open accesslog",
|
|
|
|
current_domain->domain);
|
2013-06-05 09:47:08 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
2013-06-24 11:32:45 +02:00
|
|
|
}
|
2013-06-05 09:47:08 +02:00
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
current_domain->accesslog = open(argv[1],
|
2013-11-19 17:27:14 +01:00
|
|
|
O_CREAT | O_APPEND | O_WRONLY,
|
|
|
|
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
2013-06-24 11:32:45 +02:00
|
|
|
if (current_domain->accesslog == -1) {
|
|
|
|
kore_debug("open(%s): %s", argv[1], errno_s);
|
2013-06-05 09:47:08 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-06-24 09:36:40 +02:00
|
|
|
static int
|
2013-06-24 11:32:45 +02:00
|
|
|
configure_certfile(char **argv)
|
2013-06-24 09:36:40 +02:00
|
|
|
{
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
if (current_domain == NULL) {
|
2013-09-22 20:11:56 +02:00
|
|
|
printf("missing domain for certfile\n");
|
2013-06-24 09:36:40 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
if (current_domain->certfile != NULL) {
|
|
|
|
kore_debug("domain already has a certfile set");
|
2013-06-24 09:36:40 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
current_domain->certfile = kore_strdup(argv[1]);
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
configure_certkey(char **argv)
|
|
|
|
{
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
if (current_domain == NULL) {
|
2013-09-22 20:11:56 +02:00
|
|
|
printf("missing domain for certkey\n");
|
2013-06-24 09:36:40 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
if (current_domain->certkey != NULL) {
|
|
|
|
kore_debug("domain already has a certkey set");
|
2013-06-24 09:36:40 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
current_domain->certkey = kore_strdup(argv[1]);
|
2013-06-24 09:36:40 +02:00
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
2013-06-24 11:32:45 +02:00
|
|
|
|
2013-06-26 16:37:22 +02:00
|
|
|
static int
|
|
|
|
configure_max_connections(char **argv)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
2013-08-13 16:13:43 +02:00
|
|
|
worker_max_connections = kore_strtonum(argv[1], 10, 1, 65535, &err);
|
2013-09-22 20:11:56 +02:00
|
|
|
if (err != KORE_RESULT_OK) {
|
|
|
|
printf("bad value for worker_max_connections: %s\n", argv[1]);
|
2013-06-26 16:37:22 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
2013-09-22 20:11:56 +02:00
|
|
|
}
|
2013-06-26 16:37:22 +02:00
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2014-07-31 09:14:03 +02:00
|
|
|
static int
|
|
|
|
configure_rlimit_nofiles(char **argv)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
worker_rlimit_nofiles = kore_strtonum(argv[1], 10, 1, UINT_MAX, &err);
|
|
|
|
if (err != KORE_RESULT_OK) {
|
|
|
|
printf("bad value for worker_rlimit_nofiles: %s\n", argv[1]);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-09-22 20:05:24 +02:00
|
|
|
static int
|
|
|
|
configure_http_header_max(char **argv)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
if (http_header_max != HTTP_HEADER_MAX_LEN) {
|
|
|
|
kore_debug("http_header_max already set");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
http_header_max = kore_strtonum(argv[1], 10, 1, 65535, &err);
|
|
|
|
if (err != KORE_RESULT_OK) {
|
|
|
|
printf("bad http_header_max value: %s\n", argv[1]);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-10-08 11:03:14 +02:00
|
|
|
configure_http_body_max(char **argv)
|
2013-09-22 20:05:24 +02:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
2014-10-08 11:03:14 +02:00
|
|
|
if (http_body_max != HTTP_BODY_MAX_LEN) {
|
|
|
|
kore_debug("http_body_max already set");
|
2013-09-22 20:05:24 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
2014-10-08 11:03:14 +02:00
|
|
|
http_body_max = kore_strtonum(argv[1], 10, 1, LONG_MAX, &err);
|
2013-09-22 20:05:24 +02:00
|
|
|
if (err != KORE_RESULT_OK) {
|
2014-10-08 11:03:14 +02:00
|
|
|
printf("bad http_body_max value: %s\n", argv[1]);
|
2013-09-22 20:05:24 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-10-15 10:44:56 +02:00
|
|
|
static int
|
|
|
|
configure_http_hsts_enable(char **argv)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
if (http_hsts_enable != HTTP_HSTS_ENABLE) {
|
|
|
|
kore_debug("http_hsts_enable already set");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
2013-12-16 18:00:33 +01:00
|
|
|
http_hsts_enable = kore_strtonum(argv[1], 10, 0, LONG_MAX, &err);
|
2013-10-15 10:44:56 +02:00
|
|
|
if (err != KORE_RESULT_OK) {
|
|
|
|
printf("bad http_hsts_enable value: %s\n", argv[1]);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-10-15 11:10:45 +02:00
|
|
|
static int
|
|
|
|
configure_http_keepalive_time(char **argv)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argv[1] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
if (http_keepalive_time != HTTP_KEEPALIVE_TIME) {
|
|
|
|
kore_debug("http_keepalive_time already set");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
http_keepalive_time = kore_strtonum(argv[1], 10, 0, USHRT_MAX, &err);
|
|
|
|
if (err != KORE_RESULT_OK) {
|
|
|
|
printf("bad http_keepalive_time value: %s\n", argv[1]);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-11-09 16:21:52 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-11-10 15:17:15 +01:00
|
|
|
static int
|
|
|
|
configure_params(char **argv)
|
|
|
|
{
|
|
|
|
struct kore_module_handle *hdlr;
|
|
|
|
|
|
|
|
if (current_domain == NULL) {
|
|
|
|
printf("params keyword used in wrong context\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_handler != NULL) {
|
|
|
|
printf("previous params block not closed\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv[2] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
if (!strcasecmp(argv[1], "post")) {
|
|
|
|
current_method = HTTP_METHOD_POST;
|
|
|
|
} else if (!strcasecmp(argv[1], "get")) {
|
|
|
|
current_method = HTTP_METHOD_GET;
|
|
|
|
} else {
|
|
|
|
printf("unknown method: %s in params block for %s\n",
|
|
|
|
argv[1], argv[2]);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the handler ourselves, otherwise the regex is applied
|
|
|
|
* in case of a dynamic page.
|
|
|
|
*/
|
|
|
|
TAILQ_FOREACH(hdlr, &(current_domain->handlers), list) {
|
|
|
|
if (!strcmp(hdlr->path, argv[2])) {
|
|
|
|
current_handler = hdlr;
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("params for unknown page handler: %s\n", argv[2]);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
configure_validate(char **argv)
|
|
|
|
{
|
|
|
|
struct kore_handler_params *p;
|
|
|
|
struct kore_validator *val;
|
|
|
|
|
|
|
|
if (current_handler == NULL) {
|
|
|
|
printf("validate keyword used in wrong context\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv[2] == NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
if ((val = kore_validator_lookup(argv[2])) == NULL) {
|
|
|
|
printf("unknown validator %s for %s\n", argv[2], argv[1]);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
p = kore_malloc(sizeof(*p));
|
|
|
|
p->validator = val;
|
|
|
|
p->method = current_method;
|
|
|
|
p->name = kore_strdup(argv[1]);
|
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&(current_handler->params), p, list);
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2014-01-22 22:55:10 +01:00
|
|
|
static int
|
|
|
|
configure_authentication(char **argv)
|
|
|
|
{
|
|
|
|
if (argv[2] == NULL) {
|
|
|
|
printf("Missing name for authentication block\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_auth != NULL) {
|
|
|
|
printf("Previous authentication block not closed\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(argv[2], "{")) {
|
|
|
|
printf("missing { for authentication block\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!kore_auth_new(argv[1]))
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
current_auth = kore_auth_lookup(argv[1]);
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
configure_authentication_type(char **argv)
|
|
|
|
{
|
|
|
|
if (current_auth == NULL) {
|
|
|
|
printf("authentication_type outside authentication block\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv[1] == NULL) {
|
|
|
|
printf("missing parameter for authentication_type\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(argv[1], "cookie")) {
|
|
|
|
current_auth->type = KORE_AUTH_TYPE_COOKIE;
|
2014-01-22 23:11:52 +01:00
|
|
|
} else if (!strcmp(argv[1], "header")) {
|
|
|
|
current_auth->type = KORE_AUTH_TYPE_HEADER;
|
2014-01-22 22:55:10 +01:00
|
|
|
} else {
|
|
|
|
printf("unknown authentication type '%s'\n", argv[1]);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
configure_authentication_value(char **argv)
|
|
|
|
{
|
|
|
|
if (current_auth == NULL) {
|
|
|
|
printf("authentication_value outside authentication block\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv[1] == NULL) {
|
|
|
|
printf("missing parameter for authentication_value\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_auth->value != NULL) {
|
|
|
|
printf("duplicate authentication_value found\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
current_auth->value = kore_strdup(argv[1]);
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
configure_authentication_validator(char **argv)
|
|
|
|
{
|
|
|
|
struct kore_validator *val;
|
|
|
|
|
|
|
|
if (current_auth == NULL) {
|
|
|
|
printf("authentication_validator outside authentication\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv[1] == NULL) {
|
|
|
|
printf("missing parameter for authentication_validator\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_auth->validator != NULL) {
|
|
|
|
printf("duplicate authentication_validator found\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((val = kore_validator_lookup(argv[1])) == NULL) {
|
|
|
|
printf("authentication validator '%s' not found\n", argv[1]);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
current_auth->validator = val;
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
configure_authentication_uri(char **argv)
|
|
|
|
{
|
|
|
|
if (current_auth == NULL) {
|
|
|
|
printf("authentication_uri outside authentication block\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv[1] == NULL) {
|
|
|
|
printf("missing parameter for authentication_uri\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_auth->redirect != NULL) {
|
|
|
|
printf("duplicate authentication_uri found\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
current_auth->redirect = kore_strdup(argv[1]);
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
static void
|
|
|
|
domain_sslstart(void)
|
|
|
|
{
|
|
|
|
kore_domain_sslstart(current_domain);
|
|
|
|
current_domain = NULL;
|
|
|
|
}
|
2014-07-04 09:14:05 +02:00
|
|
|
|
|
|
|
#if defined(KORE_USE_PGSQL)
|
|
|
|
|
|
|
|
static int
|
|
|
|
configure_pgsql_conn_max(char **argv)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argv[1] == NULL) {
|
|
|
|
printf("missing parameter for pgsql_conn_max\n");
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
pgsql_conn_max = kore_strtonum(argv[1], 10, 0, USHRT_MAX, &err);
|
|
|
|
if (err != KORE_RESULT_OK) {
|
|
|
|
printf("bad value for pgsql_conn_max: %s\n", argv[1]);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|