diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | debug.h | 2 | ||||
-rw-r--r-- | gconfig.c | 191 | ||||
-rw-r--r-- | gconfig.h | 5 | ||||
-rw-r--r-- | radsecproxy.c | 187 | ||||
-rw-r--r-- | radsecproxy.h | 10 | ||||
-rw-r--r-- | util.h | 6 |
8 files changed, 215 insertions, 191 deletions
@@ -1,6 +1,6 @@ CFLAGS = -g -Wall -pedantic -pthread LDFLAGS = -lssl -OBJ = util.o debug.o list.o radsecproxy.o +OBJ = util.o debug.o list.o gconfig.o radsecproxy.o all: radsecproxy diff --git a/Makefile.am b/Makefile.am index 032226e..acf4223 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,11 +1,14 @@ sbin_PROGRAMS = radsecproxy radsecproxy_SOURCES = radsecproxy.c \ + gconfig.c \ util.c \ debug.c \ list.c \ radsecproxy.h \ + gconfig.h \ debug.h \ + util.h \ list.h radsecproxy_CFLAGS = -g -Wall -pedantic -pthread @SSL_CFLAGS@ @@ -6,6 +6,8 @@ * copyright notice and this permission notice appear in all copies. */ +#include <stdint.h> + #define DBG_DBG 8 #define DBG_INFO 16 #define DBG_WARN 32 diff --git a/gconfig.c b/gconfig.c new file mode 100644 index 0000000..8040190 --- /dev/null +++ b/gconfig.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2007 Stig Venaas <venaas@uninett.no> + * + * 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. + */ + +#include <string.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include "debug.h" +#include "util.h" +#include "gconfig.h" + +/* returns NULL on error, where to continue parsing if token and ok. E.g. "" will return token with empty string */ +char *strtokenquote(char *s, char **token, char *del, char *quote, char *comment) { + char *t = s, *q, *r; + + if (!t || !token || !del) + return NULL; + while (*t && strchr(del, *t)) + t++; + if (!*t || (comment && strchr(comment, *t))) { + *token = NULL; + return t + 1; /* needs to be non-NULL, but value doesn't matter */ + } + if (quote && (q = strchr(quote, *t))) { + t++; + r = t; + while (*t && *t != *q) + t++; + if (!*t || (t[1] && !strchr(del, t[1]))) + return NULL; + *t = '\0'; + *token = r; + return t + 1; + } + *token = t; + t++; + while (*t && !strchr(del, *t)) + t++; + *t = '\0'; + return t + 1; +} + +/* Parses config with following syntax: + * One of these: + * option-name value + * option-name = value + * Or: + * option-name value { + * option-name [=] value + * ... + * } + */ +void getgenericconfig(FILE *f, char *block, ...) { + va_list ap; + char line[1024]; + /* initialise lots of stuff to avoid stupid compiler warnings */ + char *tokens[3], *s, *opt = NULL, *val = NULL, *word, *optval, **str = NULL, ***mstr = NULL; + int type = 0, tcount, conftype = 0, n; + void (*cbk)(FILE *, char *, char *, char *) = NULL; + + while (fgets(line, 1024, f)) { + s = line; + for (tcount = 0; tcount < 3; tcount++) { + s = strtokenquote(s, &tokens[tcount], " \t\r\n", "\"'", tcount ? NULL : "#"); + if (!s) + debugx(1, DBG_ERR, "Syntax error in line starting with: %s", line); + if (!tokens[tcount]) + break; + } + if (!tcount || **tokens == '#') + continue; + + if (**tokens == '}') { + if (block) + return; + debugx(1, DBG_ERR, "configuration error, found } with no matching {"); + } + + switch (tcount) { + case 2: + opt = tokens[0]; + val = tokens[1]; + conftype = CONF_STR; + break; + case 3: + if (tokens[1][0] == '=' && tokens[1][1] == '\0') { + opt = tokens[0]; + val = tokens[2]; + conftype = CONF_STR; + break; + } + if (tokens[2][0] == '{' && tokens[2][1] == '\0') { + opt = tokens[0]; + val = tokens[1]; + conftype = CONF_CBK; + break; + } + /* fall through */ + default: + if (block) + debugx(1, DBG_ERR, "configuration error in block %s, line starting with %s", block, tokens[0]); + debugx(1, DBG_ERR, "configuration error, syntax error in line starting with %s", tokens[0]); + } + + if (!*val) + debugx(1, DBG_ERR, "configuration error, option %s needs a non-empty value", opt); + + va_start(ap, block); + while ((word = va_arg(ap, char *))) { + type = va_arg(ap, int); + switch (type) { + case CONF_STR: + str = va_arg(ap, char **); + if (!str) + debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error"); + break; + case CONF_MSTR: + mstr = va_arg(ap, char ***); + if (!mstr) + debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error"); + break; + case CONF_CBK: + cbk = va_arg(ap, void (*)(FILE *, char *, char *, char *)); + break; + default: + debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error"); + } + if (!strcasecmp(opt, word)) + break; + } + va_end(ap); + + if (!word) { + if (block) + debugx(1, DBG_ERR, "configuration error in block %s, unknown option %s", block, opt); + debugx(1, DBG_ERR, "configuration error, unknown option %s", opt); + } + + if (((type == CONF_STR || type == CONF_MSTR) && conftype != CONF_STR) || + (type == CONF_CBK && conftype != CONF_CBK)) { + if (block) + debugx(1, DBG_ERR, "configuration error in block %s, wrong syntax for option %s", block, opt); + debugx(1, DBG_ERR, "configuration error, wrong syntax for option %s", opt); + } + + switch (type) { + case CONF_STR: + if (block) + debug(DBG_DBG, "getgeneralconfig: block %s: %s = %s", block, opt, val); + else + debug(DBG_DBG, "getgeneralconfig: %s = %s", opt, val); + if (*str) + debugx(1, DBG_ERR, "configuration error, option %s already set to %s", opt, *str); + *str = stringcopy(val, 0); + if (!*str) + debugx(1, DBG_ERR, "malloc failed"); + break; + case CONF_MSTR: + if (block) + debug(DBG_DBG, "getgeneralconfig: block %s: %s = %s", block, opt, val); + else + debug(DBG_DBG, "getgeneralconfig: %s = %s", opt, val); + if (*mstr) + for (n = 0; (*mstr)[n]; n++); + else + n = 0; + *mstr = realloc(*mstr, sizeof(char *) * (n + 2)); + if (!*mstr) + debugx(1, DBG_ERR, "malloc failed"); + (*mstr)[n] = stringcopy(val, 0); + (*mstr)[n + 1] = NULL; + break; + case CONF_CBK: + optval = malloc(strlen(opt) + strlen(val) + 2); + if (!optval) + debugx(1, DBG_ERR, "malloc failed"); + sprintf(optval, "%s %s", opt, val); + cbk(f, optval, opt, val); + free(optval); + break; + default: + debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error"); + } + } +} diff --git a/gconfig.h b/gconfig.h new file mode 100644 index 0000000..d546b08 --- /dev/null +++ b/gconfig.h @@ -0,0 +1,5 @@ +#define CONF_STR 1 +#define CONF_CBK 2 +#define CONF_MSTR 3 + +void getgenericconfig(FILE *f, char *block, ...); diff --git a/radsecproxy.c b/radsecproxy.c index 1002ec3..ea55c17 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -48,6 +48,8 @@ #include <openssl/x509v3.h> #include "debug.h" #include "list.h" +#include "util.h" +#include "gconfig.h" #include "radsecproxy.h" static struct options options; @@ -2453,181 +2455,6 @@ FILE *openconfigfile(const char *filename) { return f; } -/* returns NULL on error, where to continue parsing if token and ok. E.g. "" will return token with empty string */ -char *strtokenquote(char *s, char **token, char *del, char *quote, char *comment) { - char *t = s, *q, *r; - - if (!t || !token || !del) - return NULL; - while (*t && strchr(del, *t)) - t++; - if (!*t || (comment && strchr(comment, *t))) { - *token = NULL; - return t + 1; /* needs to be non-NULL, but value doesn't matter */ - } - if (quote && (q = strchr(quote, *t))) { - t++; - r = t; - while (*t && *t != *q) - t++; - if (!*t || (t[1] && !strchr(del, t[1]))) - return NULL; - *t = '\0'; - *token = r; - return t + 1; - } - *token = t; - t++; - while (*t && !strchr(del, *t)) - t++; - *t = '\0'; - return t + 1; -} - -/* Parses config with following syntax: - * One of these: - * option-name value - * option-name = value - * Or: - * option-name value { - * option-name [=] value - * ... - * } - */ -void getgeneralconfig(FILE *f, char *block, ...) { - va_list ap; - char line[1024]; - /* initialise lots of stuff to avoid stupid compiler warnings */ - char *tokens[3], *s, *opt = NULL, *val = NULL, *word, *optval, **str = NULL, ***mstr = NULL; - int type = 0, tcount, conftype = 0, n; - void (*cbk)(FILE *, char *, char *, char *) = NULL; - - while (fgets(line, 1024, f)) { - s = line; - for (tcount = 0; tcount < 3; tcount++) { - s = strtokenquote(s, &tokens[tcount], " \t\r\n", "\"'", tcount ? NULL : "#"); - if (!s) - debugx(1, DBG_ERR, "Syntax error in line starting with: %s", line); - if (!tokens[tcount]) - break; - } - if (!tcount || **tokens == '#') - continue; - - if (**tokens == '}') { - if (block) - return; - debugx(1, DBG_ERR, "configuration error, found } with no matching {"); - } - - switch (tcount) { - case 2: - opt = tokens[0]; - val = tokens[1]; - conftype = CONF_STR; - break; - case 3: - if (tokens[1][0] == '=' && tokens[1][1] == '\0') { - opt = tokens[0]; - val = tokens[2]; - conftype = CONF_STR; - break; - } - if (tokens[2][0] == '{' && tokens[2][1] == '\0') { - opt = tokens[0]; - val = tokens[1]; - conftype = CONF_CBK; - break; - } - /* fall through */ - default: - if (block) - debugx(1, DBG_ERR, "configuration error in block %s, line starting with %s", block, tokens[0]); - debugx(1, DBG_ERR, "configuration error, syntax error in line starting with %s", tokens[0]); - } - - if (!*val) - debugx(1, DBG_ERR, "configuration error, option %s needs a non-empty value", opt); - - va_start(ap, block); - while ((word = va_arg(ap, char *))) { - type = va_arg(ap, int); - switch (type) { - case CONF_STR: - str = va_arg(ap, char **); - if (!str) - debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error"); - break; - case CONF_MSTR: - mstr = va_arg(ap, char ***); - if (!mstr) - debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error"); - break; - case CONF_CBK: - cbk = va_arg(ap, void (*)(FILE *, char *, char *, char *)); - break; - default: - debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error"); - } - if (!strcasecmp(opt, word)) - break; - } - va_end(ap); - - if (!word) { - if (block) - debugx(1, DBG_ERR, "configuration error in block %s, unknown option %s", block, opt); - debugx(1, DBG_ERR, "configuration error, unknown option %s", opt); - } - - if (((type == CONF_STR || type == CONF_MSTR) && conftype != CONF_STR) || - (type == CONF_CBK && conftype != CONF_CBK)) { - if (block) - debugx(1, DBG_ERR, "configuration error in block %s, wrong syntax for option %s", block, opt); - debugx(1, DBG_ERR, "configuration error, wrong syntax for option %s", opt); - } - - switch (type) { - case CONF_STR: - if (block) - debug(DBG_DBG, "getgeneralconfig: block %s: %s = %s", block, opt, val); - else - debug(DBG_DBG, "getgeneralconfig: %s = %s", opt, val); - if (*str) - debugx(1, DBG_ERR, "configuration error, option %s already set to %s", opt, *str); - *str = stringcopy(val, 0); - if (!*str) - debugx(1, DBG_ERR, "malloc failed"); - break; - case CONF_MSTR: - if (block) - debug(DBG_DBG, "getgeneralconfig: block %s: %s = %s", block, opt, val); - else - debug(DBG_DBG, "getgeneralconfig: %s = %s", opt, val); - if (*mstr) - for (n = 0; (*mstr)[n]; n++); - else - n = 0; - *mstr = realloc(*mstr, sizeof(char *) * (n + 2)); - if (!*mstr) - debugx(1, DBG_ERR, "malloc failed"); - (*mstr)[n] = stringcopy(val, 0); - (*mstr)[n + 1] = NULL; - break; - case CONF_CBK: - optval = malloc(strlen(opt) + strlen(val) + 2); - if (!optval) - debugx(1, DBG_ERR, "malloc failed"); - sprintf(optval, "%s %s", opt, val); - cbk(f, optval, opt, val); - free(optval); - break; - default: - debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error"); - } - } -} - int addmatchcertattr(struct clsrvconf *conf, char *matchcertattr) { char *v; @@ -2706,7 +2533,7 @@ void confclient_cb(FILE *f, char *block, char *opt, char *val) { debugx(1, DBG_ERR, "malloc failed"); memset(conf, 0, sizeof(struct clsrvconf)); - getgeneralconfig(f, block, + getgenericconfig(f, block, "type", CONF_STR, &type, "host", CONF_STR, &conf->host, "secret", CONF_STR, &conf->secret, @@ -2766,7 +2593,7 @@ void confserver_cb(FILE *f, char *block, char *opt, char *val) { debugx(1, DBG_ERR, "malloc failed"); memset(conf, 0, sizeof(struct clsrvconf)); - getgeneralconfig(f, block, + getgenericconfig(f, block, "type", CONF_STR, &type, "host", CONF_STR, &conf->host, "port", CONF_STR, &conf->port, @@ -2827,7 +2654,7 @@ void confrealm_cb(FILE *f, char *block, char *opt, char *val) { debug(DBG_DBG, "confrealm_cb called for %s", block); - getgeneralconfig(f, block, + getgenericconfig(f, block, "server", CONF_MSTR, &servers, "ReplyMessage", CONF_STR, &msg, NULL @@ -2842,7 +2669,7 @@ void conftls_cb(FILE *f, char *block, char *opt, char *val) { debug(DBG_DBG, "conftls_cb called for %s", block); - getgeneralconfig(f, block, + getgenericconfig(f, block, "CACertificateFile", CONF_STR, &cacertfile, "CACertificatePath", CONF_STR, &cacertpath, "CertificateFile", CONF_STR, &certfile, @@ -2882,7 +2709,7 @@ void getmainconfig(const char *configfile) { if (!tlsconfs) debugx(1, DBG_ERR, "malloc failed"); - getgeneralconfig(f, NULL, + getgenericconfig(f, NULL, "ListenUDP", CONF_STR, &options.listenudp, "ListenTCP", CONF_STR, &options.listentcp, "ListenAccountingUDP", CONF_STR, &options.listenaccudp, diff --git a/radsecproxy.h b/radsecproxy.h index ba363ce..ee321f8 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -38,10 +38,6 @@ #define RAD_VS_ATTR_MS_MPPE_Send_Key 16 #define RAD_VS_ATTR_MS_MPPE_Recv_Key 17 -#define CONF_STR 1 -#define CONF_CBK 2 -#define CONF_MSTR 3 - struct options { char *listenudp; char *listentcp; @@ -140,9 +136,3 @@ struct tls { #define SOCKADDR_SIZE(addr) ((addr).ss_family == AF_INET ? \ sizeof(struct sockaddr_in) : \ sizeof(struct sockaddr_in6)) - -char *stringcopy(char *s, int len); -char *addr2string(struct sockaddr *addr, socklen_t len); -void printfchars(char *prefixfmt, char *prefix, char *charfmt, char *chars, int len); -int bindport(int type, char *port); -int connectport(int type, char *host, char *port); @@ -0,0 +1,6 @@ +#include <sys/socket.h> + +char *stringcopy(char *s, int len); +char *addr2string(struct sockaddr *addr, socklen_t len); +void printfchars(char *prefixfmt, char *prefix, char *charfmt, char *chars, int len); +int connectport(int type, char *host, char *port); |