diff options
-rw-r--r-- | radsecproxy.c | 138 | ||||
-rw-r--r-- | radsecproxy.h | 9 |
2 files changed, 89 insertions, 58 deletions
diff --git a/radsecproxy.c b/radsecproxy.c index 120b5d1..0a3af75 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -63,11 +63,6 @@ static struct options options; struct list *clconfs, *srvconfs, *realms, *tlsconfs, *rewriteconfs; -static int client_udp_count = 0; -static int client_tls_count = 0; -static int server_udp_count = 0; -static int server_tls_count = 0; - static struct addrinfo *srcudpres = NULL; static struct addrinfo *srctcpres = NULL; @@ -88,20 +83,38 @@ void freeclsrvconf(struct clsrvconf *conf); void freerqdata(struct request *rq); static const struct protodefs protodefs[] = { - { /* UDP, assuming RAD_UDP defined as 0 */ + { "udp", /* UDP, assuming RAD_UDP defined as 0 */ + NULL, /* secretdefault */ REQUEST_RETRY_COUNT, /* retrycountdefault */ 10, /* retrycountmax */ REQUEST_RETRY_INTERVAL, /* retryintervaldefault */ 60 /* retryintervalmax */ }, - { /* TLS, assuming RAD_TLS defined as 1 */ + { "tls", /* TLS, assuming RAD_TLS defined as 1 */ + "mysecret", /* secretdefault */ + 0, /* retrycountdefault */ + 0, /* retrycountmax */ + REQUEST_RETRY_INTERVAL * REQUEST_RETRY_COUNT, /* retryintervaldefault */ + 60 /* retryintervalmax */ + }, + { "tcp", /* TCP, assuming RAD_TCP defined as 2 */ + NULL, /* secretdefault */ 0, /* retrycountdefault */ 0, /* retrycountmax */ REQUEST_RETRY_INTERVAL * REQUEST_RETRY_COUNT, /* retryintervaldefault */ 60 /* retryintervalmax */ + }, + { NULL } }; +uint8_t protoname2int(const char *name) { + int i; + + for (i = 0; protodefs[i].name && strcasecmp(protodefs[i].name, name); i++); + return i; +} + /* callbacks for making OpenSSL thread safe */ unsigned long ssl_thread_id() { return (unsigned long)pthread_self(); @@ -452,6 +465,22 @@ struct clsrvconf *find_conf(uint8_t type, struct sockaddr *addr, struct list *co return NULL; } +/* returns next config of given type, or NULL */ +struct clsrvconf *find_conf_type(uint8_t type, struct list *confs, struct list_node **cur) { + struct list_node *entry; + struct clsrvconf *conf; + + for (entry = (cur && *cur ? list_next(*cur) : list_first(confs)); entry; entry = list_next(entry)) { + conf = (struct clsrvconf *)entry->data; + if (conf->type == type) { + if (cur) + *cur = entry; + return conf; + } + } + return NULL; +} + struct replyq *newreplyq() { struct replyq *replyq; @@ -3373,7 +3402,6 @@ void addrewrite(char *value, char **attrs, char **vattrs) { void freeclsrvconf(struct clsrvconf *conf) { free(conf->name); - free(conf->conftype); free(conf->host); free(conf->port); free(conf->secret); @@ -3418,7 +3446,6 @@ int mergeconfstring(char **dst, char **src) { /* assumes dst is a shallow copy */ int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) { if (!mergeconfstring(&dst->name, &src->name) || - !mergeconfstring(&dst->conftype, &src->conftype) || !mergeconfstring(&dst->host, &src->host) || !mergeconfstring(&dst->port, &src->port) || !mergeconfstring(&dst->secret, &src->secret) || @@ -3427,6 +3454,8 @@ int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) { !mergeconfstring(&dst->confrewrite, &src->confrewrite) || !mergeconfstring(&dst->dynamiclookupcommand, &src->dynamiclookupcommand)) return 0; + if (src->pdef) + dst->pdef = src->pdef; dst->statusserver = src->statusserver; dst->certnamecheck = src->certnamecheck; if (src->retryinterval != 255) @@ -3435,9 +3464,10 @@ int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) { dst->retrycount = src->retrycount; return 1; } - + int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { struct clsrvconf *conf; + char *conftype = NULL; debug(DBG_DBG, "confclient_cb called for %s", block); @@ -3448,7 +3478,7 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char conf->certnamecheck = 1; if (!getgenericconfig(cf, block, - "type", CONF_STR, &conf->conftype, + "type", CONF_STR, &conftype, "host", CONF_STR, &conf->host, "secret", CONF_STR, &conf->secret, "tls", CONF_STR, &conf->tls, @@ -3463,20 +3493,22 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char conf->name = stringcopy(val, 0); if (!conf->host) conf->host = stringcopy(val, 0); + + if (!conftype) + debugx(1, DBG_ERR, "error in block %s, option type missing", block); + conf->type = protoname2int(conftype); + conf->pdef = &protodefs[conf->type]; + if (!conf->pdef->name) + debugx(1, DBG_ERR, "error in block %s, unknown transport %s", block, conftype); + free(conftype); - if (conf->conftype && !strcasecmp(conf->conftype, "udp")) { - conf->type = RAD_UDP; - client_udp_count++; - } else if (conf->conftype && !strcasecmp(conf->conftype, "tls")) { + if (conf->type == RAD_TLS) { conf->ssl_ctx = conf->tls ? tlsgetctx(conf->tls, NULL) : tlsgetctx("defaultclient", "default"); if (!conf->ssl_ctx) debugx(1, DBG_ERR, "error in block %s, no tls context defined", block); if (conf->matchcertattr && !addmatchcertattr(conf)) debugx(1, DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block); - conf->type = RAD_TLS; - client_tls_count++; - } else - debugx(1, DBG_ERR, "error in block %s, type must be set to UDP or TLS", block); + } conf->rewrite = conf->confrewrite ? getrewrite(conf->confrewrite, NULL) : getrewrite("defaultclient", "default"); @@ -3489,9 +3521,11 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)"); if (!conf->secret) { - if (conf->type != RAD_TLS) - debugx(1, DBG_ERR, "error in block %s, secret must be specified when not TLS", block); - conf->secret = stringcopy(DEFAULT_TLS_SECRET, 0); + if (!conf->pdef->secretdefault) + debugx(1, DBG_ERR, "error in block %s, secret must be specified for transport type %s", block, conf->pdef->name); + conf->secret = stringcopy(conf->pdef->secretdefault, 0); + if (!conf->secret) + debugx(1, DBG_ERR, "malloc failed"); } return 1; } @@ -3523,10 +3557,13 @@ int compileserverconfig(struct clsrvconf *conf, const char *block) { conf->retrycount = protodefs[conf->type].retrycountdefault; conf->rewrite = conf->confrewrite ? getrewrite(conf->confrewrite, NULL) : getrewrite("defaultserver", "default"); + if (!conf->secret) { - if (conf->type != RAD_TLS) - debug(DBG_ERR, "error in block %s, secret must be specified when not TLS", block); - conf->secret = stringcopy(DEFAULT_TLS_SECRET, 0); + if (!conf->pdef->secretdefault) { + debug(DBG_ERR, "error in block %s, secret must be specified for transport type %s", block, conf->pdef->name); + return 0; + } + conf->secret = stringcopy(conf->pdef->secretdefault, 0); if (!conf->secret) { debug(DBG_ERR, "malloc failed"); return 0; @@ -3542,7 +3579,7 @@ int compileserverconfig(struct clsrvconf *conf, const char *block) { int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { struct clsrvconf *conf, *resconf; - const struct protodefs *pdef; + char *conftype = NULL; long int retryinterval = LONG_MIN, retrycount = LONG_MIN; debug(DBG_DBG, "confserver_cb called for %s", block); @@ -3561,7 +3598,7 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char conf->certnamecheck = 1; if (!getgenericconfig(cf, block, - "type", CONF_STR, &conf->conftype, + "type", CONF_STR, &conftype, "host", CONF_STR, &conf->host, "port", CONF_STR, &conf->port, "secret", CONF_STR, &conf->secret, @@ -3591,20 +3628,21 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char goto errexit; } } - - if (conf->conftype && !strcasecmp(conf->conftype, "udp")) - conf->type = RAD_UDP; - else if (conf->conftype && !strcasecmp(conf->conftype, "tls")) - conf->type = RAD_TLS; - else { - debug(DBG_ERR, "error in block %s, type must be set to UDP or TLS", block); + + if (!conftype) + debugx(1, DBG_ERR, "error in block %s, option type missing", block); + conf->type = protoname2int(conftype); + conf->pdef = &protodefs[conf->type]; + if (!conf->pdef->name) { + debug(DBG_ERR, "error in block %s, unknown transport %s", block, conftype); + free(conftype); goto errexit; } - pdef = &protodefs[conf->type]; - + free(conftype); + if (retryinterval != LONG_MIN) { - if (retryinterval < 1 || retryinterval > pdef->retryintervalmax) { - debug(DBG_ERR, "error in block %s, value of option RetryInterval is %d, must be 1-%d", block, retryinterval, pdef->retryintervalmax); + if (retryinterval < 1 || retryinterval > conf->pdef->retryintervalmax) { + debug(DBG_ERR, "error in block %s, value of option RetryInterval is %d, must be 1-%d", block, retryinterval, conf->pdef->retryintervalmax); goto errexit; } conf->retryinterval = (uint8_t)retryinterval; @@ -3612,8 +3650,8 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char conf->retryinterval = 255; if (retrycount != LONG_MIN) { - if (retrycount < 0 || retrycount > pdef->retrycountmax) { - debug(DBG_ERR, "error in block %s, value of option RetryCount is %d, must be 0-%d", block, pdef->retrycountmax); + if (retrycount < 0 || retrycount > conf->pdef->retrycountmax) { + debug(DBG_ERR, "error in block %s, value of option RetryCount is %d, must be 0-%d", block, retrycount, conf->pdef->retrycountmax); goto errexit; } conf->retrycount = (uint8_t)retrycount; @@ -3639,17 +3677,6 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char if (resconf) return 1; - switch (conf->type) { - case RAD_UDP: - server_udp_count++; - break; - case RAD_TLS: - server_tls_count++; - break; - default: - goto errexit; - } - if (!list_push(srvconfs, conf)) { debug(DBG_ERR, "malloc failed"); goto errexit; @@ -3751,6 +3778,7 @@ void getmainconfig(const char *configfile) { if (!getgenericconfig(&cfs, NULL, "ListenUDP", CONF_MSTR, &options.listenudp, "ListenTCP", CONF_MSTR, &options.listentcp, + "ListenTLS", CONF_MSTR, &options.listentls, "ListenAccountingUDP", CONF_MSTR, &options.listenaccudp, "SourceUDP", CONF_STR, &options.sourceudp, "SourceTCP", CONF_STR, &options.sourcetcp, @@ -3886,8 +3914,8 @@ int main(int argc, char **argv) { sigaddset(&sigset, SIGPIPE); pthread_sigmask(SIG_BLOCK, &sigset, NULL); pthread_create(&sigth, NULL, sighandler, NULL); - - if (client_udp_count) { + + if (find_conf_type(RAD_UDP, clconfs, NULL)) { udp_server_replyq = newreplyq(); if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL)) debugx(1, DBG_ERR, "pthread_create failed"); @@ -3918,8 +3946,8 @@ int main(int argc, char **argv) { if (pthread_create(&udpclient6rdth, NULL, udpclientrd, (void *)&udp_client6_sock)) debugx(1, DBG_ERR, "pthread_create failed"); - if (client_tls_count) - createlisteners(RAD_TLS, options.listentcp, 0); + if (find_conf_type(RAD_TLS, clconfs, NULL)) + createlisteners(RAD_TLS, options.listentls, 0); /* just hang around doing nothing, anything to do here? */ for (;;) diff --git a/radsecproxy.h b/radsecproxy.h index aaa49c6..d371bb7 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -12,7 +12,6 @@ /* MAX_REQUESTS must be 256 due to Radius' 8 bit ID field */ #define MAX_REQUESTS 256 -#define DEFAULT_TLS_SECRET "mysecret" #define DEFAULT_UDP_PORT "1812" #define DEFAULT_TLS_PORT "2083" #define REQUEST_RETRY_INTERVAL 5 @@ -31,6 +30,7 @@ #define RAD_UDP 0 #define RAD_TLS 1 +#define RAD_TCP 2 #define RAD_Attr_User_Name 1 #define RAD_Attr_User_Password 2 @@ -46,6 +46,7 @@ struct options { char **listenudp; char **listentcp; + char **listentls; char **listenaccudp; char *sourceudp; char *sourcetcp; @@ -88,8 +89,8 @@ struct listenerarg { struct clsrvconf { char *name; - char *conftype; - uint8_t type; /* RAD_UDP/RAD_TLS */ + uint8_t type; /* RAD_UDP/RAD_TLS/RAD_TCP */ + const struct protodefs *pdef; char *host; char *port; char *secret; @@ -166,6 +167,8 @@ struct rewriteconf { }; struct protodefs { + char *name; + char *secretdefault; uint8_t retrycountdefault; uint8_t retrycountmax; uint8_t retryintervaldefault; |