summaryrefslogtreecommitdiff
path: root/radsecproxy.c
diff options
context:
space:
mode:
authorvenaas <venaas>2008-04-16 12:13:11 +0000
committervenaas <venaas@e88ac4ed-0b26-0410-9574-a7f39faa03bf>2008-04-16 12:13:11 +0000
commita96826ac5aa9bdf465af9cd2f54bd8466b47feb1 (patch)
tree7b24067d1672731cd678302b19fcc298b403c229 /radsecproxy.c
parent889ceec39a92a9e5bd1fd761367884f304768bc6 (diff)
started adding improved tls client code, not tested
git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@236 e88ac4ed-0b26-0410-9574-a7f39faa03bf
Diffstat (limited to 'radsecproxy.c')
-rw-r--r--radsecproxy.c152
1 files changed, 125 insertions, 27 deletions
diff --git a/radsecproxy.c b/radsecproxy.c
index f7ca114..7402b2d 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -336,13 +336,11 @@ int prefixmatch(void *a1, void *a2, uint8_t len) {
return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]);
}
-/* returns the config with matching address, or NULL */
-/* if conf argument is not NULL, we only check that one */
-struct clsrvconf *find_conf(char type, struct sockaddr *addr, struct list *confs, struct clsrvconf *conf) {
+/* check if conf has matching address */
+struct clsrvconf *checkconfaddr(char type, struct sockaddr *addr, struct clsrvconf *conf) {
struct sockaddr_in6 *sa6 = NULL;
struct in_addr *a4 = NULL;
struct addrinfo *res;
- struct list_node *entry;
if (addr->sa_family == AF_INET6) {
sa6 = (struct sockaddr_in6 *)addr;
@@ -353,29 +351,45 @@ struct clsrvconf *find_conf(char type, struct sockaddr *addr, struct list *confs
} else
a4 = &((struct sockaddr_in *)addr)->sin_addr;
- if (conf) {
- if (conf->type == type) {
- if (conf->prefixlen == 255) {
- for (res = conf->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 conf;
- } else {
- res = conf->addrinfo;
- if (res &&
- ((a4 && res->ai_family == AF_INET &&
- prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, conf->prefixlen)) ||
- (sa6 && res->ai_family == AF_INET6 &&
- prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, conf->prefixlen))))
+ if (conf->type == type) {
+ if (conf->prefixlen == 255) {
+ for (res = conf->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 conf;
- }
+ } else {
+ res = conf->addrinfo;
+ if (res &&
+ ((a4 && res->ai_family == AF_INET &&
+ prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, conf->prefixlen)) ||
+ (sa6 && res->ai_family == AF_INET6 &&
+ prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, conf->prefixlen))))
+ return conf;
}
- return NULL;
}
+ return NULL;
+}
+
+/* returns next config with matching address, or NULL */
+struct clsrvconf *find_conf(char type, struct sockaddr *addr, struct list *confs, struct list_node **cur) {
+ struct sockaddr_in6 *sa6 = NULL;
+ struct in_addr *a4 = NULL;
+ struct addrinfo *res;
+ struct list_node *entry;
+ struct clsrvconf *conf;
+
+ 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];
+ sa6 = NULL;
+ }
+ } else
+ a4 = &((struct sockaddr_in *)addr)->sin_addr;
- for (entry = list_first(confs); entry; entry = list_next(entry)) {
+ for (cur ? list_next(*cur) : list_first(confs); entry; entry = list_next(entry)) {
conf = (struct clsrvconf *)entry->data;
if (conf->type == type) {
if (conf->prefixlen == 255) {
@@ -383,16 +397,22 @@ struct clsrvconf *find_conf(char type, struct sockaddr *addr, struct list *confs
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)))
+ !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16))) {
+ if (cur)
+ *cur = entry;
return conf;
+ }
} else {
res = conf->addrinfo;
if (res &&
((a4 && res->ai_family == AF_INET &&
prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, conf->prefixlen)) ||
(sa6 && res->ai_family == AF_INET6 &&
- prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, conf->prefixlen))))
+ prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, conf->prefixlen)))) {
+ if (cur)
+ *cur = entry;
return conf;
+ }
}
}
}
@@ -558,12 +578,12 @@ unsigned char *radudpget(int s, struct client **client, struct server **server,
if (client)
if (*client)
- p = find_conf('U', (struct sockaddr *)&from, NULL, (*client)->conf);
+ p = checkconfaddr('U', (struct sockaddr *)&from, (*client)->conf);
else
p = find_conf('U', (struct sockaddr *)&from, clconfs, NULL);
else
if (*server)
- p = find_conf('U', (struct sockaddr *)&from, NULL, (*server)->conf);
+ p = checkconfaddr('U', (struct sockaddr *)&from, (*server)->conf);
else
p = find_conf('U', (struct sockaddr *)&from, srvconfs, NULL);
@@ -2331,6 +2351,84 @@ void *tlsserverrd(void *arg) {
pthread_exit(NULL);
}
+/***********************************************
+ * new tls listening code
+ ***********************************************/
+void *tlsserverrd2(void *arg) {
+ int s;
+ struct sockaddr_storage from;
+ size_t fromlen = sizeof(from);
+ struct clsrvconf *conf;
+ struct list_node *cur = NULL;
+ SSL *ssl = NULL;
+ struct client *client;
+
+ s = *(int *)arg;
+ if (getpeername(s, (struct sockaddr *)&from, &fromlen)) {
+ debug(DBG_DBG, "tlsserverrd: getpeername failed, exiting");
+ goto errexit;
+ }
+ debug(DBG_WARN, "incoming TLS connection from %s", addr2string((struct sockaddr *)&from, fromlen));
+ while ((conf = find_conf('T', (struct sockaddr *)&from, clconfs, &cur))) {
+ if (!ssl) {
+ ssl = SSL_new(conf->ssl_ctx);
+ SSL_set_fd(ssl, s);
+ }
+ client = addclient(conf);
+ if (!client) {
+ debug(DBG_WARN, "Failed to create new client instance");
+ goto errexit;
+ }
+ /* todo */
+ client->ssl = ssl;
+ /* todo */
+ }
+ debug(DBG_WARN, "ignoring request, no matching TLS client");
+
+ errexit:
+ if (ssl)
+ SSL_free(ssl);
+ shutdown(s, SHUT_RDWR);
+ close(s);
+ pthread_exit(NULL);
+}
+
+int tlslistener2() {
+ pthread_t tlsserverth;
+ int s, snew;
+ struct sockaddr_storage from;
+ size_t fromlen = sizeof(from);
+ struct clsrvconf *listenres;
+
+ listenres = resolve_hostport('T', options.listentcp, DEFAULT_TLS_PORT);
+ if ((s = bindtoaddr(listenres->addrinfo, AF_UNSPEC, 1, 0)) < 0)
+ debugx(1, DBG_ERR, "tlslistener: socket/bind failed");
+
+ listen(s, 0);
+ debug(DBG_WARN, "listening for incoming TCP on %s:%s", listenres->host ? listenres->host : "*", listenres->port);
+ free(listenres);
+
+ for (;;) {
+ snew = accept(s, (struct sockaddr *)&from, &fromlen);
+ if (snew < 0) {
+ debug(DBG_WARN, "accept failed");
+ continue;
+ }
+ if (pthread_create(&tlsserverth, NULL, tlsserverrd2, (void *)&snew)) {
+ debug(DBG_ERR, "tlslistener: pthread_create failed");
+ shutdown(snew, SHUT_RDWR);
+ close(snew);
+ continue;
+ }
+ pthread_detach(tlsserverth);
+ }
+ return 0;
+}
+
+/***********************************************
+ * end of new tls listening code
+ ***********************************************/
+
int tlslistener() {
pthread_t tlsserverth;
int s, snew;