summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvenaas <venaas>2007-06-17 21:01:56 +0000
committervenaas <venaas@e88ac4ed-0b26-0410-9574-a7f39faa03bf>2007-06-17 21:01:56 +0000
commitc36b0869b9c0092d7bb06a3267364f675a657ae0 (patch)
treef845dc1c6ae6e1afab7e3eae749446472f9b5002
parent6d5e3bd8d51d1bfa0350ad0c9e2cea97e9fb4f29 (diff)
restructuring peer and client/server
git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@136 e88ac4ed-0b26-0410-9574-a7f39faa03bf
-rw-r--r--radsecproxy.c369
-rw-r--r--radsecproxy.h10
2 files changed, 215 insertions, 164 deletions
diff --git a/radsecproxy.c b/radsecproxy.c
index 3cf2a74..fafa506 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -47,22 +47,22 @@
#include "radsecproxy.h"
static struct options options;
-static struct client *clients = NULL;
-static struct server *servers = NULL;
+static struct clsrvconf *clconfs = NULL;
+static struct clsrvconf *srvconfs = NULL;
static struct realm *realms = NULL;
static struct tls *tls = NULL;
static int client_udp_count = 0;
static int client_tls_count = 0;
-static int client_count = 0;
+static int clconf_count = 0;
static int server_udp_count = 0;
static int server_tls_count = 0;
-static int server_count = 0;
+static int srvconf_count = 0;
static int realm_count = 0;
static int tls_count = 0;
-static struct peer *tcp_server_listen;
-static struct peer *udp_server_listen;
+static struct clsrvconf *tcp_server_listen;
+static struct clsrvconf *udp_server_listen;
static struct replyq udp_server_replyq;
static int udp_server_sock = -1;
static pthread_mutex_t *ssl_locks;
@@ -143,21 +143,21 @@ void printauth(char *s, unsigned char *t) {
}
#endif
-int resolvepeer(struct peer *peer, int ai_flags) {
+int resolvepeer(struct clsrvconf *conf, int ai_flags) {
struct addrinfo hints, *addrinfo;
memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = (peer->type == 'T' ? SOCK_STREAM : SOCK_DGRAM);
+ hints.ai_socktype = (conf->type == 'T' ? SOCK_STREAM : SOCK_DGRAM);
hints.ai_family = AF_UNSPEC;
hints.ai_flags = ai_flags;
- if (getaddrinfo(peer->host, peer->port, &hints, &addrinfo)) {
- debug(DBG_WARN, "resolvepeer: can't resolve %s port %s", peer->host, peer->port);
+ if (getaddrinfo(conf->host, conf->port, &hints, &addrinfo)) {
+ debug(DBG_WARN, "resolvepeer: can't resolve %s port %s", conf->host, conf->port);
return 0;
}
- if (peer->addrinfo)
- freeaddrinfo(peer->addrinfo);
- peer->addrinfo = addrinfo;
+ if (conf->addrinfo)
+ freeaddrinfo(conf->addrinfo);
+ conf->addrinfo = addrinfo;
return 1;
}
@@ -200,6 +200,35 @@ int bindtoaddr(struct addrinfo *addrinfo) {
return -1;
}
+/* returns the peer with matching address, or NULL */
+/* if peer argument is not NULL, we only check that one client */
+struct clsrvconf *find_peer(char type, struct sockaddr *addr, struct clsrvconf *confs, int count) {
+ struct sockaddr_in6 *sa6 = NULL;
+ struct in_addr *a4 = NULL;
+ int i;
+ struct addrinfo *res;
+
+ if (addr->sa_family == AF_INET6) {
+ sa6 = (struct sockaddr_in6 *)addr;
+ if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr))
+ a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12];
+ } else
+ a4 = &((struct sockaddr_in *)addr)->sin_addr;
+
+ for (i = 0; i < count; i++) {
+ if (confs->type == type)
+ for (res = confs->addrinfo; res; res = res->ai_next)
+ if ((a4 && res->ai_family == AF_INET &&
+ !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
+ (sa6 && res->ai_family == AF_INET6 &&
+ !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16)))
+ return confs;
+ confs++;
+ }
+ return NULL;
+}
+
+#if 0
/* returns the client with matching address, or NULL */
/* if client argument is not NULL, we only check that one client */
struct client *find_client(char type, struct sockaddr *addr, struct client *client) {
@@ -263,16 +292,18 @@ struct server *find_server(char type, struct sockaddr *addr, struct server *serv
}
return NULL;
}
+#endif
/* exactly one of client and server must be non-NULL */
+/* should probably take peer list (client(s) or server(s)) as argument instead */
/* if *peer == NULL we return who we received from, else require it to be from peer */
/* return from in sa if not NULL */
unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) {
- int cnt, len;
- void *f;
+ int cnt, len, confcount;
unsigned char buf[65536], *rad;
struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
+ struct clsrvconf *confs, *p;
for (;;) {
cnt = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
@@ -300,10 +331,25 @@ unsigned char *radudpget(int s, struct client **client, struct server **server,
if (cnt > len)
debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len);
- f = (client
- ? (void *)find_client('U', (struct sockaddr *)&from, *client)
- : (void *)find_server('U', (struct sockaddr *)&from, *server));
- if (!f) {
+ if (client)
+ if (*client) {
+ confcount = 1;
+ confs = (*client)->conf;
+ } else {
+ confcount = clconf_count;
+ confs = clconfs;
+ }
+ else
+ if (*server) {
+ confcount = 1;
+ confs = (*server)->conf;
+ } else {
+ confcount = srvconf_count;
+ confs = srvconfs;
+ }
+
+ p = find_peer('U', (struct sockaddr *)&from, confs, confcount);
+ if (!p) {
debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer, ignoring");
continue;
}
@@ -314,16 +360,16 @@ unsigned char *radudpget(int s, struct client **client, struct server **server,
debug(DBG_ERR, "radudpget: malloc failed");
}
memcpy(rad, buf, len);
- if (client)
- *client = (struct client *)f; /* only need this if *client == NULL, but if not NULL *client == f here */
- else
- *server = (struct server *)f; /* only need this if *server == NULL, but if not NULL *server == f here */
+ if (client && !*client)
+ *client = p->clients;
+ else if (server && !*server)
+ *server = p->servers;
if (sa)
*sa = from;
return rad;
}
-int tlsverifycert(SSL *ssl, struct peer *peer) {
+int tlsverifycert(SSL *ssl, struct clsrvconf *conf) {
int l, loc;
X509 *cert;
X509_NAME *nm;
@@ -362,11 +408,11 @@ int tlsverifycert(SSL *ssl, struct peer *peer) {
printf("\n");
}
#endif
- if (l == strlen(peer->host) && !strncasecmp(peer->host, (char *)v, l)) {
- debug(DBG_DBG, "tlsverifycert: Found cn matching host %s, All OK", peer->host);
+ if (l == strlen(conf->host) && !strncasecmp(conf->host, (char *)v, l)) {
+ debug(DBG_DBG, "tlsverifycert: Found cn matching host %s, All OK", conf->host);
return 1;
}
- debug(DBG_ERR, "tlsverifycert: cn not matching host %s", peer->host);
+ debug(DBG_ERR, "tlsverifycert: cn not matching host %s", conf->host);
}
X509_free(cert);
return 0;
@@ -403,21 +449,21 @@ void tlsconnect(struct server *server, struct timeval *when, char *text) {
sleep(600);
} else
server->lastconnecttry.tv_sec = now.tv_sec; /* no sleep at startup */
- debug(DBG_WARN, "tlsconnect: trying to open TLS connection to %s port %s", server->peer->host, server->peer->port);
+ debug(DBG_WARN, "tlsconnect: trying to open TLS connection to %s port %s", server->conf->host, server->conf->port);
if (server->sock >= 0)
close(server->sock);
- if ((server->sock = connecttoserver(server->peer->addrinfo)) < 0) {
+ if ((server->sock = connecttoserver(server->conf->addrinfo)) < 0) {
debug(DBG_ERR, "tlsconnect: connecttoserver failed");
continue;
}
SSL_free(server->ssl);
- server->ssl = SSL_new(server->peer->ssl_ctx);
+ server->ssl = SSL_new(server->conf->ssl_ctx);
SSL_set_fd(server->ssl, server->sock);
- if (SSL_connect(server->ssl) > 0 && tlsverifycert(server->ssl, server->peer))
+ if (SSL_connect(server->ssl) > 0 && tlsverifycert(server->ssl, server->conf))
break;
}
- debug(DBG_WARN, "tlsconnect: TLS connection to %s port %s up", server->peer->host, server->peer->port);
+ debug(DBG_WARN, "tlsconnect: TLS connection to %s port %s up", server->conf->host, server->conf->port);
gettimeofday(&server->lastconnecttry, NULL);
pthread_mutex_unlock(&server->lock);
}
@@ -478,9 +524,9 @@ int clientradput(struct server *server, unsigned char *rad) {
struct timeval lastconnecttry;
len = RADLEN(rad);
- if (server->peer->type == 'U') {
+ if (server->conf->type == 'U') {
if (send(server->sock, rad, len, 0) >= 0) {
- debug(DBG_DBG, "clienradput: sent UDP of length %d to %s port %s", len, server->peer->host, server->peer->port);
+ debug(DBG_DBG, "clienradput: sent UDP of length %d to %s port %s", len, server->conf->host, server->conf->port);
return 1;
}
debug(DBG_WARN, "clientradput: send failed");
@@ -497,7 +543,7 @@ int clientradput(struct server *server, unsigned char *rad) {
server->connectionok = 1;
debug(DBG_DBG, "clientradput: Sent %d bytes, Radius packet of length %d to TLS peer %s",
- cnt, len, server->peer->host);
+ cnt, len, server->conf->host);
return 1;
}
@@ -651,13 +697,13 @@ void sendrq(struct server *to, struct request *rq) {
rq->buf[1] = (char)i;
attr = attrget(rq->buf + 20, RADLEN(rq->buf) - 20, RAD_Attr_Message_Authenticator);
- if (attr && !createmessageauth(rq->buf, ATTRVAL(attr), to->peer->secret)) {
+ if (attr && !createmessageauth(rq->buf, ATTRVAL(attr), to->conf->secret)) {
free(rq->buf);
pthread_mutex_unlock(&to->newrq_mutex);
return;
}
- debug(DBG_DBG, "sendrq: inserting packet with id %d in queue for %s", i, to->peer->host);
+ debug(DBG_DBG, "sendrq: inserting packet with id %d in queue for %s", i, to->conf->host);
to->requests[i] = *rq;
to->nextid = i + 1;
@@ -672,7 +718,7 @@ void sendrq(struct server *to, struct request *rq) {
void sendreply(struct client *to, unsigned char *buf, struct sockaddr_storage *tosa) {
struct replyq *replyq = to->replyq;
- if (!radsign(buf, (unsigned char *)to->peer->secret)) {
+ if (!radsign(buf, (unsigned char *)to->conf->secret)) {
free(buf);
debug(DBG_WARN, "sendreply: failed to sign message");
return;
@@ -1050,8 +1096,8 @@ void respondstatusserver(struct request *rq) {
resp[0] = RAD_Access_Accept;
resp[2] = 0;
resp[3] = 20;
- debug(DBG_DBG, "respondstatusserver: responding to %s", rq->from->peer->host);
- sendreply(rq->from, resp, rq->from->peer->type == 'U' ? &rq->fromsa : NULL);
+ debug(DBG_DBG, "respondstatusserver: responding to %s", rq->from->conf->host);
+ sendreply(rq->from, resp, rq->from->conf->type == 'U' ? &rq->fromsa : NULL);
}
void respondreject(struct request *rq, char *message) {
@@ -1074,7 +1120,7 @@ void respondreject(struct request *rq, char *message) {
resp[21] = len - 20;
memcpy(resp + 22, message, len - 22);
}
- sendreply(rq->from, resp, rq->from->peer->type == 'U' ? &rq->fromsa : NULL);
+ sendreply(rq->from, resp, rq->from->conf->type == 'U' ? &rq->fromsa : NULL);
}
void radsrv(struct request *rq) {
@@ -1125,17 +1171,17 @@ void radsrv(struct request *rq) {
free(buf);
return;
}
- to = realm->server;
+ to = realm->srvconf->servers;
if (to && rqinqueue(to, rq->from, id)) {
- debug(DBG_INFO, "radsrv: already got request from host %s with id %d, ignoring", rq->from->peer->host, id);
+ debug(DBG_INFO, "radsrv: already got request from host %s with id %d, ignoring", rq->from->conf->host, id);
free(buf);
return;
}
}
attr = attrget(attrs, len, RAD_Attr_Message_Authenticator);
- if (attr && (ATTRVALLEN(attr) != 16 || !checkmessageauth(buf, ATTRVAL(attr), rq->from->peer->secret))) {
+ if (attr && (ATTRVALLEN(attr) != 16 || !checkmessageauth(buf, ATTRVAL(attr), rq->from->conf->secret))) {
debug(DBG_WARN, "radsrv: message authentication failed");
free(buf);
return;
@@ -1147,7 +1193,7 @@ void radsrv(struct request *rq) {
}
if (!to) {
- debug(DBG_INFO, "radsrv: sending reject to %s for %s", rq->from->peer->host, username);
+ debug(DBG_INFO, "radsrv: sending reject to %s for %s", rq->from->conf->host, username);
respondreject(rq, realm->message);
return;
}
@@ -1165,7 +1211,7 @@ void radsrv(struct request *rq) {
attr = attrget(attrs, len, RAD_Attr_User_Password);
if (attr) {
debug(DBG_DBG, "radsrv: found userpwdattr with value length %d", ATTRVALLEN(attr));
- if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->peer->secret, to->peer->secret, auth, newauth)) {
+ if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->conf->secret, to->conf->secret, auth, newauth)) {
free(buf);
return;
}
@@ -1174,7 +1220,7 @@ void radsrv(struct request *rq) {
attr = attrget(attrs, len, RAD_Attr_Tunnel_Password);
if (attr) {
debug(DBG_DBG, "radsrv: found tunnelpwdattr with value length %d", ATTRVALLEN(attr));
- if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->peer->secret, to->peer->secret, auth, newauth)) {
+ if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->conf->secret, to->conf->secret, auth, newauth)) {
free(buf);
return;
}
@@ -1197,8 +1243,8 @@ void *clientrd(void *arg) {
for (;;) {
lastconnecttry = server->lastconnecttry;
- buf = (server->peer->type == 'U' ? radudpget(server->sock, NULL, &server, NULL) : radtlsget(server->ssl));
- if (!buf && server->peer->type == 'T') {
+ buf = (server->conf->type == 'U' ? radudpget(server->sock, NULL, &server, NULL) : radtlsget(server->ssl));
+ if (!buf && server->conf->type == 'T') {
tlsconnect(server, &lastconnecttry, "clientrd");
continue;
}
@@ -1238,7 +1284,7 @@ void *clientrd(void *arg) {
continue;
}
- if (!validauth(buf, server->requests[i].buf + 4, (unsigned char *)server->peer->secret)) {
+ if (!validauth(buf, server->requests[i].buf + 4, (unsigned char *)server->conf->secret)) {
pthread_mutex_unlock(&server->newrq_mutex);
free(buf);
debug(DBG_WARN, "clientrd: invalid auth, ignoring");
@@ -1267,7 +1313,7 @@ void *clientrd(void *arg) {
}
memcpy(tmp, buf + 4, 16);
memcpy(buf + 4, server->requests[i].buf + 4, 16);
- if (!checkmessageauth(buf, ATTRVAL(messageauth), server->peer->secret)) {
+ if (!checkmessageauth(buf, ATTRVAL(messageauth), server->conf->secret)) {
pthread_mutex_unlock(&server->newrq_mutex);
free(buf);
debug(DBG_WARN, "clientrd: message authentication failed");
@@ -1281,7 +1327,7 @@ void *clientrd(void *arg) {
server->requests[i].received = 1;
pthread_mutex_unlock(&server->newrq_mutex);
free(buf);
- debug(DBG_INFO, "clientrd: got status server response from %s", server->peer->host);
+ debug(DBG_INFO, "clientrd: got status server response from %s", server->conf->host);
continue;
}
@@ -1297,9 +1343,9 @@ void *clientrd(void *arg) {
subattrs = ATTRVAL(attr) + 4;
if (!attrvalidate(subattrs, sublen) ||
!msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Send_Key, "MS MPPE Send Key",
- server->requests + i, server->peer->secret, from->peer->secret) ||
+ server->requests + i, server->conf->secret, from->conf->secret) ||
!msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Recv_Key, "MS MPPE Recv Key",
- server->requests + i, server->peer->secret, from->peer->secret))
+ server->requests + i, server->conf->secret, from->conf->secret))
break;
}
if (attr) {
@@ -1316,10 +1362,10 @@ void *clientrd(void *arg) {
tmp[ATTRVALLEN(attr)] = '\0';
switch (*buf) {
case RAD_Access_Accept:
- debug(DBG_INFO, "Access Accept for %s from %s", tmp, server->peer->host);
+ debug(DBG_INFO, "Access Accept for %s from %s", tmp, server->conf->host);
break;
case RAD_Access_Reject:
- debug(DBG_INFO, "Access Reject for %s from %s", tmp, server->peer->host);
+ debug(DBG_INFO, "Access Reject for %s from %s", tmp, server->conf->host);
break;
}
}
@@ -1332,7 +1378,7 @@ void *clientrd(void *arg) {
#endif
if (messageauth) {
- if (!createmessageauth(buf, ATTRVAL(messageauth), from->peer->secret)) {
+ if (!createmessageauth(buf, ATTRVAL(messageauth), from->conf->secret)) {
pthread_mutex_unlock(&server->newrq_mutex);
free(buf);
continue;
@@ -1340,13 +1386,13 @@ void *clientrd(void *arg) {
debug(DBG_DBG, "clientrd: computed messageauthattr");
}
- if (from->peer->type == 'U')
+ if (from->conf->type == 'U')
fromsa = server->requests[i].fromsa;
server->requests[i].received = 1;
pthread_mutex_unlock(&server->newrq_mutex);
debug(DBG_DBG, "clientrd: giving packet back to where it came from");
- sendreply(from, buf, from->peer->type == 'U' ? &fromsa : NULL);
+ sendreply(from, buf, from->conf->type == 'U' ? &fromsa : NULL);
}
}
@@ -1363,7 +1409,7 @@ void *clientwr(void *arg) {
memset(&timeout, 0, sizeof(struct timespec));
- if (server->peer->statusserver) {
+ if (server->conf->statusserver) {
memset(&statsrvrq, 0, sizeof(struct request));
memset(statsrvbuf, 0, sizeof(statsrvbuf));
statsrvbuf[0] = RAD_Status_Server;
@@ -1373,8 +1419,8 @@ void *clientwr(void *arg) {
gettimeofday(&lastsend, NULL);
}
- if (server->peer->type == 'U') {
- if ((server->sock = connecttoserver(server->peer->addrinfo)) < 0)
+ if (server->conf->type == 'U') {
+ if ((server->sock = connecttoserver(server->conf->addrinfo)) < 0)
debugx(1, DBG_ERR, "clientwr: connecttoserver failed");
} else
tlsconnect(server, NULL, "new client");
@@ -1386,7 +1432,7 @@ void *clientwr(void *arg) {
pthread_mutex_lock(&server->newrq_mutex);
if (!server->newrq) {
gettimeofday(&now, NULL);
- if (server->peer->statusserver) {
+ if (server->conf->statusserver) {
/* random 0-7 seconds */
RAND_bytes(&rnd, 1);
rnd /= 32;
@@ -1439,11 +1485,11 @@ void *clientwr(void *arg) {
continue;
}
- if (rq->tries == (*rq->buf == RAD_Status_Server || server->peer->type == 'T'
+ if (rq->tries == (*rq->buf == RAD_Status_Server || server->conf->type == 'T'
? 1 : REQUEST_RETRIES)) {
debug(DBG_DBG, "clientwr: removing expired packet from queue");
if (*rq->buf == RAD_Status_Server)
- debug(DBG_WARN, "clientwr: no status server response, %s dead?", server->peer->host);
+ debug(DBG_WARN, "clientwr: no status server response, %s dead?", server->conf->host);
free(rq->buf);
/* setting this to NULL means that it can be reused */
rq->buf = NULL;
@@ -1453,7 +1499,7 @@ void *clientwr(void *arg) {
pthread_mutex_unlock(&server->newrq_mutex);
rq->expiry.tv_sec = now.tv_sec +
- (*rq->buf == RAD_Status_Server || server->peer->type == 'T'
+ (*rq->buf == RAD_Status_Server || server->conf->type == 'T'
? REQUEST_EXPIRY : REQUEST_EXPIRY / REQUEST_RETRIES);
if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
timeout.tv_sec = rq->expiry.tv_sec;
@@ -1461,7 +1507,7 @@ void *clientwr(void *arg) {
clientradput(server, server->requests[i].buf);
gettimeofday(&lastsend, NULL);
}
- if (server->peer->statusserver) {
+ if (server->conf->statusserver) {
gettimeofday(&now, NULL);
if (now.tv_sec - lastsend.tv_sec >= STATUS_SERVER_PERIOD) {
if (!RAND_bytes(statsrvbuf + 4, 16)) {
@@ -1474,7 +1520,7 @@ void *clientwr(void *arg) {
continue;
}
memcpy(statsrvrq.buf, statsrvbuf, sizeof(statsrvbuf));
- debug(DBG_DBG, "clientwr: sending status server to %s", server->peer->host);
+ debug(DBG_DBG, "clientwr: sending status server to %s", server->conf->host);
lastsend.tv_sec = now.tv_sec;
sendrq(server, &statsrvrq);
}
@@ -1533,7 +1579,7 @@ void *tlsserverwr(void *arg) {
struct client *client = (struct client *)arg;
struct replyq *replyq;
- debug(DBG_DBG, "tlsserverwr starting for %s", client->peer->host);
+ debug(DBG_DBG, "tlsserverwr starting for %s", client->conf->host);
replyq = client->replyq;
pthread_mutex_lock(&replyq->count_mutex);
for (;;) {
@@ -1574,7 +1620,7 @@ void *tlsserverrd(void *arg) {
pthread_t tlsserverwrth;
SSL *ssl;
- debug(DBG_DBG, "tlsserverrd starting for %s", client->peer->host);
+ debug(DBG_DBG, "tlsserverrd starting for %s", client->conf->host);
ssl = client->ssl;
if (SSL_accept(ssl) <= 0) {
@@ -1583,7 +1629,7 @@ void *tlsserverrd(void *arg) {
debug(DBG_ERR, "SSL_accept failed");
goto errexit;
}
- if (tlsverifycert(client->ssl, client->peer)) {
+ if (tlsverifycert(client->ssl, client->conf)) {
if (pthread_create(&tlsserverwrth, NULL, tlsserverwr, (void *)client)) {
debug(DBG_ERR, "tlsserverrd: pthread_create failed");
goto errexit;
@@ -1593,7 +1639,7 @@ void *tlsserverrd(void *arg) {
rq.buf = radtlsget(client->ssl);
if (!rq.buf)
break;
- debug(DBG_DBG, "tlsserverrd: got Radius message from %s", client->peer->host);
+ debug(DBG_DBG, "tlsserverrd: got Radius message from %s", client->conf->host);
rq.from = client;
radsrv(&rq);
}
@@ -1612,7 +1658,7 @@ void *tlsserverrd(void *arg) {
SSL_free(ssl);
shutdown(s, SHUT_RDWR);
close(s);
- debug(DBG_DBG, "tlsserverrd thread for %s exiting", client->peer->host);
+ debug(DBG_DBG, "tlsserverrd thread for %s exiting", client->conf->host);
client->ssl = NULL;
pthread_exit(NULL);
}
@@ -1639,7 +1685,7 @@ int tlslistener() {
}
debug(DBG_WARN, "incoming TLS connection from %s", addr2string((struct sockaddr *)&from, fromlen));
- client = find_client('T', (struct sockaddr *)&from, NULL);
+ client = find_peer('T', (struct sockaddr *)&from, clconfs, clconf_count)->clients;
if (!client) {
debug(DBG_WARN, "ignoring request, not a known TLS client");
shutdown(snew, SHUT_RDWR);
@@ -1653,7 +1699,7 @@ int tlslistener() {
close(snew);
continue;
}
- client->ssl = SSL_new(client->peer->ssl_ctx);
+ client->ssl = SSL_new(client->conf->ssl_ctx);
SSL_set_fd(client->ssl, snew);
if (pthread_create(&tlsserverth, NULL, tlsserverrd, (void *)client)) {
debug(DBG_ERR, "tlslistener: pthread_create failed");
@@ -1765,10 +1811,10 @@ void addrealm(char *value, char *server, char *message) {
char *s, *regex = NULL;
if (server) {
- for (i = 0; i < server_count; i++)
- if (!strcasecmp(server, servers[i].peer->host))
+ for (i = 0; i < srvconf_count; i++)
+ if (!strcasecmp(server, srvconfs[i].host))
break;
- if (i == server_count)
+ if (i == srvconf_count)
debugx(1, DBG_ERR, "addrealm failed, no server %s", server);
}
@@ -1814,7 +1860,7 @@ void addrealm(char *value, char *server, char *message) {
debugx(1, DBG_ERR, "ReplyMessage can be at most 253 bytes");
realm->message = message;
if (server)
- realm->server = servers + i;
+ realm->srvconf = srvconfs + i;
if (regcomp(&realm->regex, regex ? regex : value + 1, REG_ICASE | REG_NOSUB))
debugx(1, DBG_ERR, "addrealm: failed to compile regular expression %s", regex ? regex : value + 1);
if (regex)
@@ -1822,7 +1868,7 @@ void addrealm(char *value, char *server, char *message) {
debug(DBG_DBG, "addrealm: added realm %s for server %s", value, server);
}
-char *parsehostport(char *s, struct peer *peer) {
+char *parsehostport(char *s, struct clsrvconf *conf) {
char *p, *field;
int ipv6 = 0;
@@ -1842,7 +1888,7 @@ char *parsehostport(char *s, struct peer *peer) {
if (field == p)
debugx(1, DBG_ERR, "missing host/address");
- peer->host = stringcopy(field, p - field);
+ conf->host = stringcopy(field, p - field);
if (ipv6) {
p++;
if (*p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n')
@@ -1854,9 +1900,9 @@ char *parsehostport(char *s, struct peer *peer) {
for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
if (field == p)
debugx(1, DBG_ERR, "syntax error, : but no following port");
- peer->port = stringcopy(field, p - field);
+ conf->port = stringcopy(field, p - field);
} else
- peer->port = stringcopy(peer->type == 'U' ? DEFAULT_UDP_PORT : DEFAULT_TLS_PORT, 0);
+ conf->port = stringcopy(conf->type == 'U' ? DEFAULT_UDP_PORT : DEFAULT_TLS_PORT, 0);
return p;
}
@@ -1884,27 +1930,27 @@ FILE *openconfigfile(const char *filename) {
return f;
}
-struct peer *server_create(char type) {
- struct peer *server;
- char *conf;
+struct clsrvconf *server_create(char type) {
+ struct clsrvconf *conf;
+ char *lconf;
- server = malloc(sizeof(struct peer));
- if (!server)
+ conf = malloc(sizeof(struct clsrvconf));
+ if (!conf)
debugx(1, DBG_ERR, "malloc failed");
- memset(server, 0, sizeof(struct peer));
- server->type = type;
- conf = (type == 'T' ? options.listentcp : options.listenudp);
- if (conf) {
- parsehostport(conf, server);
- if (!strcmp(server->host, "*")) {
- free(server->host);
- server->host = NULL;
+ memset(conf, 0, sizeof(struct clsrvconf));
+ conf->type = type;
+ lconf = (type == 'T' ? options.listentcp : options.listenudp);
+ if (lconf) {
+ parsehostport(lconf, conf);
+ if (!strcmp(conf->host, "*")) {
+ free(conf->host);
+ conf->host = NULL;
}
} else
- server->port = stringcopy(type == 'T' ? DEFAULT_TLS_PORT : DEFAULT_UDP_PORT, 0);
- if (!resolvepeer(server, AI_PASSIVE))
- debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", server->host, server->port);
- return server;
+ conf->port = stringcopy(type == 'T' ? DEFAULT_TLS_PORT : DEFAULT_UDP_PORT, 0);
+ if (!resolvepeer(conf, AI_PASSIVE))
+ debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host, conf->port);
+ return conf;
}
/* returns NULL on error, where to continue parsing if token and ok. E.g. "" will return token with empty string */
@@ -2059,20 +2105,15 @@ void getgeneralconfig(FILE *f, char *block, ...) {
void confclsrv_cb(FILE *f, char *block, char *opt, char *val) {
char *type = NULL, *secret = NULL, *port = NULL, *tls = NULL, *statusserver = NULL;
- struct client *client = NULL;
- struct server *server = NULL;
- struct peer *peer;
+ struct clsrvconf *clsrvconf;
debug(DBG_DBG, "confclsrv_cb called for %s", block);
/* now create client/server here, later they should be created dynamically
where peer has pointer to clients/servers using its config */
-
- peer = malloc(sizeof(struct peer));
- if (!peer)
- debugx(1, DBG_ERR, "malloc failed");
- memset(peer, 0, sizeof(struct peer));
-
+ /* instead of current clients and servers, they would be arrays of struct peer */
+ /* or rather linked lists of struct peers */
+
if (!strcasecmp(opt, "client")) {
getgeneralconfig(f, block,
"type", CONF_STR, &type,
@@ -2080,13 +2121,17 @@ void confclsrv_cb(FILE *f, char *block, char *opt, char *val) {
"tls", CONF_STR, &tls,
NULL
);
- client_count++;
- clients = realloc(clients, client_count * sizeof(struct client));
- if (!clients)
+ clconf_count++;
+ clconfs = realloc(clconfs, clconf_count * sizeof(struct clsrvconf));
+ if (!clconfs)
+ debugx(1, DBG_ERR, "malloc failed");
+ clsrvconf = clconfs + clconf_count - 1;
+ memset(clsrvconf, 0, sizeof(struct clsrvconf));
+ clsrvconf->clients = malloc(sizeof(struct client));
+ if (!clsrvconf->clients)
debugx(1, DBG_ERR, "malloc failed");
- client = clients + client_count - 1;
- memset(client, 0, sizeof(struct client));
- client->peer = peer;
+ memset(clsrvconf->clients, 0, sizeof(struct client));
+ clsrvconf->clients->conf = clsrvconf;
} else {
getgeneralconfig(f, block,
"type", CONF_STR, &type,
@@ -2096,86 +2141,90 @@ void confclsrv_cb(FILE *f, char *block, char *opt, char *val) {
"StatusServer", CONF_STR, &statusserver,
NULL
);
- server_count++;
- servers = realloc(servers, server_count * sizeof(struct server));
- if (!servers)
+ srvconf_count++;
+ srvconfs = realloc(srvconfs, srvconf_count * sizeof(struct clsrvconf));
+ if (!srvconfs)
debugx(1, DBG_ERR, "malloc failed");
- server = servers + server_count - 1;
- memset(server, 0, sizeof(struct server));
- server->peer = peer;
- peer->port = port;
+ clsrvconf = srvconfs + srvconf_count - 1;
+ memset(clsrvconf, 0, sizeof(struct server));
+ clsrvconf->servers = malloc(sizeof(struct server));
+ if (!clsrvconf->servers)
+ debugx(1, DBG_ERR, "malloc failed");
+ memset(clsrvconf->servers, 0, sizeof(struct server));
+ clsrvconf->servers->conf = clsrvconf;
+ clsrvconf->port = port;
if (statusserver) {
if (!strcasecmp(statusserver, "on"))
- peer->statusserver = 1;
+ clsrvconf->statusserver = 1;
else if (strcasecmp(statusserver, "off"))
debugx(1, DBG_ERR, "error in block %s, StatusServer is %s, must be on or off", block, statusserver);
free(statusserver);
}
}
- peer->host = stringcopy(val, 0);
+ clsrvconf->host = stringcopy(val, 0);
if (type && !strcasecmp(type, "udp")) {
- peer->type = 'U';
- if (client)
+ clsrvconf->type = 'U';
+ if (clsrvconf->clients)
client_udp_count++;
else {
server_udp_count++;
if (!port)
- peer->port = stringcopy(DEFAULT_UDP_PORT, 0);
+ clsrvconf->port = stringcopy(DEFAULT_UDP_PORT, 0);
}
} else if (type && !strcasecmp(type, "tls")) {
- if (client) {
- peer->ssl_ctx = tls ? tlsgetctx(tls, NULL) : tlsgetctx("defaultclient", "default");
+ if (clsrvconf->clients) {
+ clsrvconf->ssl_ctx = tls ? tlsgetctx(tls, NULL) : tlsgetctx("defaultclient", "default");
client_tls_count++;
} else {
- peer->ssl_ctx = tls ? tlsgetctx(tls, NULL) : tlsgetctx("defaultserver", "default");
+ clsrvconf->ssl_ctx = tls ? tlsgetctx(tls, NULL) : tlsgetctx("defaultserver", "default");
server_tls_count++;
if (!port)
- peer->port = stringcopy(DEFAULT_TLS_PORT, 0);
+ clsrvconf->port = stringcopy(DEFAULT_TLS_PORT, 0);
}
- if (!peer->ssl_ctx)
+ if (!clsrvconf->ssl_ctx)
debugx(1, DBG_ERR, "error in block %s, no tls context defined", block);
- peer->type = 'T';
+ clsrvconf->type = 'T';
} else
debugx(1, DBG_ERR, "error in block %s, type must be set to UDP or TLS", block);
free(type);
- if (!resolvepeer(peer, 0))
- debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", peer->host, peer->port);
+ if (!resolvepeer(clsrvconf, 0))
+ debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", clsrvconf->host, clsrvconf->port);
if (!secret) {
- if (peer->type == 'U')
+ if (clsrvconf->type == 'U')
debugx(1, DBG_ERR, "error in block %s, secret must be specified for UDP", block);
- peer->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
+ clsrvconf->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
} else {
- peer->secret = secret;
+ clsrvconf->secret = secret;
}
- if (client) {
- if (peer->type == 'U')
- client->replyq = &udp_server_replyq;
+ if (clsrvconf->clients) {
+ if (clsrvconf->type == 'U')
+ clsrvconf->clients->replyq = &udp_server_replyq;
else {
- client->replyq = malloc(sizeof(struct replyq));
- if (!client->replyq)
+ clsrvconf->clients->replyq = malloc(sizeof(struct replyq));
+ if (!clsrvconf->clients->replyq)
debugx(1, DBG_ERR, "malloc failed");
- client->replyq->replies = calloc(MAX_REQUESTS, sizeof(struct reply));
- if (!client->replyq->replies)
+ clsrvconf->clients->replyq->replies = calloc(MAX_REQUESTS, sizeof(struct reply));
+ if (!clsrvconf->clients->replyq->replies)
debugx(1, DBG_ERR, "malloc failed");
- client->replyq->size = MAX_REQUESTS;
- client->replyq->count = 0;
- pthread_mutex_init(&client->replyq->count_mutex, NULL);
- pthread_cond_init(&client->replyq->count_cond, NULL);
+ clsrvconf->clients->replyq->size = MAX_REQUESTS;
+ clsrvconf->clients->replyq->count = 0;
+ pthread_mutex_init(&clsrvconf->clients->replyq->count_mutex, NULL);
+ pthread_cond_init(&clsrvconf->clients->replyq->count_cond, NULL);
}
} else {
- pthread_mutex_init(&server->lock, NULL);
- server->sock = -1;
- server->requests = calloc(MAX_REQUESTS, sizeof(struct request));
- if (!server->requests)
+ pthread_mutex_init(&clsrvconf->servers->lock, NULL);
+ clsrvconf->servers->sock = -1;
+ clsrvconf->servers->requests = calloc(MAX_REQUESTS, sizeof(struct request));
+ if (!clsrvconf->servers->requests)
debugx(1, DBG_ERR, "malloc failed");
- server->newrq = 0;
- pthread_mutex_init(&server->newrq_mutex, NULL);
- pthread_cond_init(&server->newrq_cond, NULL);
+ clsrvconf->servers->newrq = 0;
+ pthread_mutex_init(&clsrvconf->servers->newrq_mutex, NULL);
+ pthread_cond_init(&clsrvconf->servers->newrq_cond, NULL);
}
}
@@ -2310,9 +2359,9 @@ int main(int argc, char **argv) {
debug_set_destination(options.logdestination);
}
- if (!server_count)
+ if (!srvconf_count)
debugx(1, DBG_ERR, "No servers configured, nothing to do, exiting");
- if (!client_count)
+ if (!clconf_count)
debugx(1, DBG_ERR, "No clients configured, nothing to do, exiting");
if (!realm_count)
debugx(1, DBG_ERR, "No realms configured, nothing to do, exiting");
@@ -2326,8 +2375,8 @@ int main(int argc, char **argv) {
debugx(1, DBG_ERR, "pthread_create failed");
}
- for (i = 0; i < server_count; i++)
- if (pthread_create(&servers[i].clientth, NULL, clientwr, (void *)&servers[i]))
+ for (i = 0; i < srvconf_count; i++)
+ if (pthread_create(&srvconfs[i].servers->clientth, NULL, clientwr, (void *)&srvconfs[i]))
debugx(1, DBG_ERR, "pthread_create failed");
if (client_tls_count) {
diff --git a/radsecproxy.h b/radsecproxy.h
index d89b1c9..3733a18 100644
--- a/radsecproxy.h
+++ b/radsecproxy.h
@@ -74,7 +74,7 @@ struct replyq {
pthread_cond_t count_cond;
};
-struct peer {
+struct clsrvconf {
char type; /* U for UDP, T for TLS */
char *host;
char *port;
@@ -82,16 +82,18 @@ struct peer {
uint8_t statusserver;
SSL_CTX *ssl_ctx;
struct addrinfo *addrinfo;
+ struct client *clients;
+ struct server *servers;
};
struct client {
- struct peer *peer;
+ struct clsrvconf *conf;
SSL *ssl;
struct replyq *replyq;
};
struct server {
- struct peer *peer;
+ struct clsrvconf *conf;
int sock;
SSL *ssl;
pthread_mutex_t lock;
@@ -109,7 +111,7 @@ struct realm {
char *name;
char *message;
regex_t regex;
- struct server *server;
+ struct clsrvconf *srvconf;
};
struct tls {