Commit e0c9e33c authored by venaas's avatar venaas Committed by venaas

moved more code to tlscommon, fixed a couple of minor lint warnings

git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@447 e88ac4ed-0b26-0410-9574-a7f39faa03bf
parent a99d921c
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#define CONF_BLN 4 #define CONF_BLN 4
#define CONF_LINT 5 #define CONF_LINT 5
#include <stdio.h>
struct gconffile { struct gconffile {
char *path; char *path;
FILE *file; FILE *file;
......
...@@ -70,13 +70,11 @@ ...@@ -70,13 +70,11 @@
#include "list.h" #include "list.h"
#include "hash.h" #include "hash.h"
#include "util.h" #include "util.h"
#include "gconfig.h"
#include "radsecproxy.h" #include "radsecproxy.h"
#include "udp.h" #include "udp.h"
#include "tcp.h" #include "tcp.h"
#include "tls.h" #include "tls.h"
#include "dtls.h" #include "dtls.h"
#include "tlscommon.h"
static struct options options; static struct options options;
static struct list *clconfs, *srvconfs; static struct list *clconfs, *srvconfs;
...@@ -515,7 +513,6 @@ void freeserver(struct server *server, uint8_t destroymutex) { ...@@ -515,7 +513,6 @@ void freeserver(struct server *server, uint8_t destroymutex) {
} }
int addserver(struct clsrvconf *conf) { int addserver(struct clsrvconf *conf) {
uint8_t type;
int i; int i;
if (conf->servers) { if (conf->servers) {
...@@ -530,10 +527,8 @@ int addserver(struct clsrvconf *conf) { ...@@ -530,10 +527,8 @@ int addserver(struct clsrvconf *conf) {
memset(conf->servers, 0, sizeof(struct server)); memset(conf->servers, 0, sizeof(struct server));
conf->servers->conf = conf; conf->servers->conf = conf;
type = conf->type; #ifdef RADPROT_DTLS
if (conf->type == RAD_DTLS)
#ifdef DRADPROT_TLS
if (type == RAD_DTLS)
conf->servers->rbios = newqueue(); conf->servers->rbios = newqueue();
#endif #endif
conf->pdef->setsrcres(); conf->pdef->setsrcres();
...@@ -585,194 +580,6 @@ int addserver(struct clsrvconf *conf) { ...@@ -585,194 +580,6 @@ int addserver(struct clsrvconf *conf) {
return 0; return 0;
} }
int subjectaltnameaddr(X509 *cert, int family, struct in6_addr *addr) {
int loc, i, l, n, r = 0;
char *v;
X509_EXTENSION *ex;
STACK_OF(GENERAL_NAME) *alt;
GENERAL_NAME *gn;
debug(DBG_DBG, "subjectaltnameaddr");
loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
if (loc < 0)
return r;
ex = X509_get_ext(cert, loc);
alt = X509V3_EXT_d2i(ex);
if (!alt)
return r;
n = sk_GENERAL_NAME_num(alt);
for (i = 0; i < n; i++) {
gn = sk_GENERAL_NAME_value(alt, i);
if (gn->type != GEN_IPADD)
continue;
r = -1;
v = (char *)ASN1_STRING_data(gn->d.ia5);
l = ASN1_STRING_length(gn->d.ia5);
if (((family == AF_INET && l == sizeof(struct in_addr)) || (family == AF_INET6 && l == sizeof(struct in6_addr)))
&& !memcmp(v, &addr, l)) {
r = 1;
break;
}
}
GENERAL_NAMES_free(alt);
return r;
}
int cnregexp(X509 *cert, char *exact, regex_t *regex) {
int loc, l;
char *v, *s;
X509_NAME *nm;
X509_NAME_ENTRY *e;
ASN1_STRING *t;
nm = X509_get_subject_name(cert);
loc = -1;
for (;;) {
loc = X509_NAME_get_index_by_NID(nm, NID_commonName, loc);
if (loc == -1)
break;
e = X509_NAME_get_entry(nm, loc);
t = X509_NAME_ENTRY_get_data(e);
v = (char *) ASN1_STRING_data(t);
l = ASN1_STRING_length(t);
if (l < 0)
continue;
if (exact) {
if (l == strlen(exact) && !strncasecmp(exact, v, l))
return 1;
} else {
s = stringcopy((char *)v, l);
if (!s) {
debug(DBG_ERR, "malloc failed");
continue;
}
if (regexec(regex, s, 0, NULL, 0)) {
free(s);
continue;
}
free(s);
return 1;
}
}
return 0;
}
int subjectaltnameregexp(X509 *cert, int type, char *exact, regex_t *regex) {
int loc, i, l, n, r = 0;
char *s, *v;
X509_EXTENSION *ex;
STACK_OF(GENERAL_NAME) *alt;
GENERAL_NAME *gn;
debug(DBG_DBG, "subjectaltnameregexp");
loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
if (loc < 0)
return r;
ex = X509_get_ext(cert, loc);
alt = X509V3_EXT_d2i(ex);
if (!alt)
return r;
n = sk_GENERAL_NAME_num(alt);
for (i = 0; i < n; i++) {
gn = sk_GENERAL_NAME_value(alt, i);
if (gn->type != type)
continue;
r = -1;
v = (char *)ASN1_STRING_data(gn->d.ia5);
l = ASN1_STRING_length(gn->d.ia5);
if (l <= 0)
continue;
#ifdef DEBUG
printfchars(NULL, gn->type == GEN_DNS ? "dns" : "uri", NULL, v, l);
#endif
if (exact) {
if (memcmp(v, exact, l))
continue;
} else {
s = stringcopy((char *)v, l);
if (!s) {
debug(DBG_ERR, "malloc failed");
continue;
}
if (regexec(regex, s, 0, NULL, 0)) {
free(s);
continue;
}
free(s);
}
r = 1;
break;
}
GENERAL_NAMES_free(alt);
return r;
}
X509 *verifytlscert(SSL *ssl) {
X509 *cert;
unsigned long error;
if (SSL_get_verify_result(ssl) != X509_V_OK) {
debug(DBG_ERR, "verifytlscert: basic validation failed");
while ((error = ERR_get_error()))
debug(DBG_ERR, "verifytlscert: TLS: %s", ERR_error_string(error, NULL));
return NULL;
}
cert = SSL_get_peer_certificate(ssl);
if (!cert)
debug(DBG_ERR, "verifytlscert: failed to obtain certificate");
return cert;
}
int verifyconfcert(X509 *cert, struct clsrvconf *conf) {
int r;
uint8_t type = 0; /* 0 for DNS, AF_INET for IPv4, AF_INET6 for IPv6 */
struct in6_addr addr;
if (conf->certnamecheck && conf->prefixlen == 255) {
if (inet_pton(AF_INET, conf->host, &addr))
type = AF_INET;
else if (inet_pton(AF_INET6, conf->host, &addr))
type = AF_INET6;
r = type ? subjectaltnameaddr(cert, type, &addr) : subjectaltnameregexp(cert, GEN_DNS, conf->host, NULL);
if (r) {
if (r < 0) {
debug(DBG_WARN, "verifyconfcert: No subjectaltname matching %s %s", type ? "address" : "host", conf->host);
return 0;
}
debug(DBG_DBG, "verifyconfcert: Found subjectaltname matching %s %s", type ? "address" : "host", conf->host);
} else {
if (!cnregexp(cert, conf->host, NULL)) {
debug(DBG_WARN, "verifyconfcert: cn not matching host %s", conf->host);
return 0;
}
debug(DBG_DBG, "verifyconfcert: Found cn matching host %s", conf->host);
}
}
if (conf->certcnregex) {
if (cnregexp(cert, NULL, conf->certcnregex) < 1) {
debug(DBG_WARN, "verifyconfcert: CN not matching regex");
return 0;
}
debug(DBG_DBG, "verifyconfcert: CN matching regex");
}
if (conf->certuriregex) {
if (subjectaltnameregexp(cert, GEN_URI, NULL, conf->certuriregex) < 1) {
debug(DBG_WARN, "verifyconfcert: subjectaltname URI not matching regex");
return 0;
}
debug(DBG_DBG, "verifyconfcert: subjectaltname URI matching regex");
}
return 1;
}
unsigned char *attrget(unsigned char *attrs, int length, uint8_t type) { unsigned char *attrget(unsigned char *attrs, int length, uint8_t type) {
while (length > 1) { while (length > 1) {
if (ATTRTYPE(attrs) == type) if (ATTRTYPE(attrs) == type)
...@@ -1286,7 +1093,7 @@ int msmppe(unsigned char *attrs, int length, uint8_t type, char *attrtxt, struct ...@@ -1286,7 +1093,7 @@ int msmppe(unsigned char *attrs, int length, uint8_t type, char *attrtxt, struct
return 1; return 1;
} }
int findvendorsubattr(uint32_t *attrs, uint32_t vendor, uint8_t subattr) { int findvendorsubattr(uint32_t *attrs, uint32_t vendor, uint32_t subattr) {
if (!attrs) if (!attrs)
return 0; return 0;
...@@ -1312,7 +1119,7 @@ int dovendorrewriterm(struct tlv *attr, uint32_t *removevendorattrs) { ...@@ -1312,7 +1119,7 @@ int dovendorrewriterm(struct tlv *attr, uint32_t *removevendorattrs) {
if (!*removevendorattrs) if (!*removevendorattrs)
return 0; return 0;
if (findvendorsubattr(removevendorattrs, vendor, -1)) if (findvendorsubattr(removevendorattrs, vendor, 256))
return 1; /* remove entire vendor attribute */ return 1; /* remove entire vendor attribute */
sublen = attr->l - 4; sublen = attr->l - 4;
...@@ -1504,7 +1311,7 @@ void addttlattr(struct radmsg *msg, uint32_t *attrtype, uint8_t addttl) { ...@@ -1504,7 +1311,7 @@ void addttlattr(struct radmsg *msg, uint32_t *attrtype, uint8_t addttl) {
memset(ttl, 0, 4); memset(ttl, 0, 4);
ttl[3] = addttl; ttl[3] = addttl;
if (attrtype[1] == -1) { /* not vendor */ if (attrtype[1] == 256) { /* not vendor */
attr = maketlv(attrtype[0], 4, ttl); attr = maketlv(attrtype[0], 4, ttl);
if (attr && !radmsg_add(msg, attr)) if (attr && !radmsg_add(msg, attr))
freetlv(attr); freetlv(attr);
...@@ -1545,7 +1352,7 @@ int checkttl(struct radmsg *msg, uint32_t *attrtype) { ...@@ -1545,7 +1352,7 @@ int checkttl(struct radmsg *msg, uint32_t *attrtype) {
uint32_t vendor; uint32_t vendor;
int sublen; int sublen;
if (attrtype[1] == -1) { /* not vendor */ if (attrtype[1] == 256) { /* not vendor */
attr = radmsg_gettype(msg, attrtype[0]); attr = radmsg_gettype(msg, attrtype[0]);
if (attr) if (attr)
return decttl(attr->l, attr->v); return decttl(attr->l, attr->v);
...@@ -2623,40 +2430,6 @@ int dynamicconfig(struct server *server) { ...@@ -2623,40 +2430,6 @@ int dynamicconfig(struct server *server) {
return 0; return 0;
} }
int addmatchcertattr(struct clsrvconf *conf) {
char *v;
regex_t **r;
if (!strncasecmp(conf->matchcertattr, "CN:/", 4)) {
r = &conf->certcnregex;
v = conf->matchcertattr + 4;
} else if (!strncasecmp(conf->matchcertattr, "SubjectAltName:URI:/", 20)) {
r = &conf->certuriregex;
v = conf->matchcertattr + 20;
} else
return 0;
if (!*v)
return 0;
/* regexp, remove optional trailing / if present */
if (v[strlen(v) - 1] == '/')
v[strlen(v) - 1] = '\0';
if (!*v)
return 0;
*r = malloc(sizeof(regex_t));
if (!*r) {
debug(DBG_ERR, "malloc failed");
return 0;
}
if (regcomp(*r, v, REG_EXTENDED | REG_ICASE | REG_NOSUB)) {
free(*r);
*r = NULL;
debug(DBG_ERR, "failed to compile regular expression %s", v);
return 0;
}
return 1;
}
/* should accept both names and numeric values, only numeric right now */ /* should accept both names and numeric values, only numeric right now */
uint8_t attrname2val(char *attrname) { uint8_t attrname2val(char *attrname) {
int val = 0; int val = 0;
...@@ -2672,11 +2445,11 @@ int vattrname2val(char *attrname, uint32_t *vendor, uint32_t *type) { ...@@ -2672,11 +2445,11 @@ int vattrname2val(char *attrname, uint32_t *vendor, uint32_t *type) {
*vendor = atoi(attrname); *vendor = atoi(attrname);
s = strchr(attrname, ':'); s = strchr(attrname, ':');
if (!s) { if (!s) {
*type = -1; *type = 256;
return 1; return 1;
} }
*type = atoi(s + 1); *type = atoi(s + 1);
return *type >= 0 && *type < 256; return *type < 256;
} }
/* should accept both names and numeric values, only numeric right now */ /* should accept both names and numeric values, only numeric right now */
...@@ -2856,7 +2629,7 @@ int setttlattr(struct options *opts, char *defaultattr) { ...@@ -2856,7 +2629,7 @@ int setttlattr(struct options *opts, char *defaultattr) {
char *ttlattr = opts->ttlattr ? opts->ttlattr : defaultattr; char *ttlattr = opts->ttlattr ? opts->ttlattr : defaultattr;
if (vattrname2val(ttlattr, opts->ttlattrtype, opts->ttlattrtype + 1) && if (vattrname2val(ttlattr, opts->ttlattrtype, opts->ttlattrtype + 1) &&
(opts->ttlattrtype[1] != -1 || opts->ttlattrtype[0] < 256)) (opts->ttlattrtype[1] != 256 || opts->ttlattrtype[0] < 256))
return 1; return 1;
debug(DBG_ERR, "setttlattr: invalid TTLAttribute value %s", ttlattr); debug(DBG_ERR, "setttlattr: invalid TTLAttribute value %s", ttlattr);
return 0; return 0;
...@@ -2953,9 +2726,11 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char ...@@ -2953,9 +2726,11 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
"type", CONF_STR, &conftype, "type", CONF_STR, &conftype,
"host", CONF_STR, &conf->host, "host", CONF_STR, &conf->host,
"secret", CONF_STR, &conf->secret, "secret", CONF_STR, &conf->secret,
#if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
"tls", CONF_STR, &conf->tls, "tls", CONF_STR, &conf->tls,
"matchcertificateattribute", CONF_STR, &conf->matchcertattr, "matchcertificateattribute", CONF_STR, &conf->matchcertattr,
"CertificateNameCheck", CONF_BLN, &conf->certnamecheck, "CertificateNameCheck", CONF_BLN, &conf->certnamecheck,
#endif
"DuplicateInterval", CONF_LINT, &dupinterval, "DuplicateInterval", CONF_LINT, &dupinterval,
"addTTL", CONF_LINT, &addttl, "addTTL", CONF_LINT, &addttl,
"rewrite", CONF_STR, &rewriteinalias, "rewrite", CONF_STR, &rewriteinalias,
...@@ -3114,8 +2889,11 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char ...@@ -3114,8 +2889,11 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
"host", CONF_STR, &conf->host, "host", CONF_STR, &conf->host,
"port", CONF_STR, &conf->port, "port", CONF_STR, &conf->port,
"secret", CONF_STR, &conf->secret, "secret", CONF_STR, &conf->secret,
#if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
"tls", CONF_STR, &conf->tls, "tls", CONF_STR, &conf->tls,
"MatchCertificateAttribute", CONF_STR, &conf->matchcertattr, "MatchCertificateAttribute", CONF_STR, &conf->matchcertattr,
"CertificateNameCheck", CONF_BLN, &conf->certnamecheck,
#endif
"addTTL", CONF_LINT, &addttl, "addTTL", CONF_LINT, &addttl,
"rewrite", CONF_STR, &rewriteinalias, "rewrite", CONF_STR, &rewriteinalias,
"rewriteIn", CONF_STR, &conf->confrewritein, "rewriteIn", CONF_STR, &conf->confrewritein,
...@@ -3123,7 +2901,6 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char ...@@ -3123,7 +2901,6 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
"StatusServer", CONF_BLN, &conf->statusserver, "StatusServer", CONF_BLN, &conf->statusserver,
"RetryInterval", CONF_LINT, &retryinterval, "RetryInterval", CONF_LINT, &retryinterval,
"RetryCount", CONF_LINT, &retrycount, "RetryCount", CONF_LINT, &retrycount,
"CertificateNameCheck", CONF_BLN, &conf->certnamecheck,
"DynamicLookupCommand", CONF_STR, &conf->dynamiclookupcommand, "DynamicLookupCommand", CONF_STR, &conf->dynamiclookupcommand,
NULL NULL
)) { )) {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "tlv11.h" #include "tlv11.h"
#include "radmsg.h" #include "radmsg.h"
#include "gconfig.h"
#define DEBUG_LEVEL 3 #define DEBUG_LEVEL 3
...@@ -106,6 +107,8 @@ struct clsrvconf { ...@@ -106,6 +107,8 @@ struct clsrvconf {
struct server *servers; struct server *servers;
}; };
#include "tlscommon.h"
struct client { struct client {
struct clsrvconf *conf; struct clsrvconf *conf;
int sock; int sock;
...@@ -204,8 +207,5 @@ void freebios(struct queue *q); ...@@ -204,8 +207,5 @@ void freebios(struct queue *q);
struct request *newrequest(); struct request *newrequest();
void freerq(struct request *rq); void freerq(struct request *rq);
int radsrv(struct request *rq); int radsrv(struct request *rq);
X509 *verifytlscert(SSL *ssl);
int verifyconfcert(X509 *cert, struct clsrvconf *conf);
void replyh(struct server *server, unsigned char *buf); void replyh(struct server *server, unsigned char *buf);
SSL_CTX *tlsgetctx(uint8_t type, struct tls *t);
struct addrinfo *resolve_hostport_addrinfo(uint8_t type, char *hostport); struct addrinfo *resolve_hostport_addrinfo(uint8_t type, char *hostport);
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
*/ */
#ifdef RADPROT_TCP
#include <signal.h> #include <signal.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
...@@ -25,12 +24,12 @@ ...@@ -25,12 +24,12 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <regex.h> #include <regex.h>
#include <pthread.h> #include <pthread.h>
#include <openssl/ssl.h>
#include "debug.h"
#include "list.h" #include "list.h"
#include "util.h"
#include "radsecproxy.h" #include "radsecproxy.h"
#ifdef RADPROT_TCP
#include "debug.h"
#include "util.h"
static void setprotoopts(struct commonprotoopts *opts); static void setprotoopts(struct commonprotoopts *opts);
static char **getlistenerargs(); static char **getlistenerargs();
void *tcplistener(void *arg); void *tcplistener(void *arg);
......
...@@ -36,26 +36,8 @@ ...@@ -36,26 +36,8 @@
#include "list.h" #include "list.h"
#include "hash.h" #include "hash.h"
#include "util.h" #include "util.h"
#include "gconfig.h"
#include "radsecproxy.h" #include "radsecproxy.h"
struct tls {
char *name;
char *cacertfile;
char *cacertpath;
char *certfile;
char *certkeyfile;
char *certkeypwd;
uint8_t crlcheck;
char **policyoids;
uint32_t cacheexpiry;
uint32_t tlsexpiry;
uint32_t dtlsexpiry;
X509_VERIFY_PARAM *vpm;
SSL_CTX *tlsctx;
SSL_CTX *dtlsctx;
};
static struct hash *tlsconfs = NULL; static struct hash *tlsconfs = NULL;
static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) { static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) {
...@@ -335,6 +317,194 @@ SSL_CTX *tlsgetctx(uint8_t type, struct tls *t) { ...@@ -335,6 +317,194 @@ SSL_CTX *tlsgetctx(uint8_t type, struct tls *t) {
return NULL; return NULL;
} }
X509 *verifytlscert(SSL *ssl) {
X509 *cert;
unsigned long error;
if (SSL_get_verify_result(ssl) != X509_V_OK) {
debug(DBG_ERR, "verifytlscert: basic validation failed");
while ((error = ERR_get_error()))
debug(DBG_ERR, "verifytlscert: TLS: %s", ERR_error_string(error, NULL));
return NULL;
}
cert = SSL_get_peer_certificate(ssl);
if (!cert)
debug(DBG_ERR, "verifytlscert: failed to obtain certificate");
return cert;
}
static int subjectaltnameaddr(X509 *cert, int family, struct in6_addr *addr) {
int loc, i, l, n, r = 0;
char *v;
X509_EXTENSION *ex;
STACK_OF(GENERAL_NAME) *alt;
GENERAL_NAME *gn;
debug(DBG_DBG, "subjectaltnameaddr");
loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
if (loc < 0)
return r;
ex = X509_get_ext(cert, loc);
alt = X509V3_EXT_d2i(ex);
if (!alt)
return r;
n = sk_GENERAL_NAME_num(alt);
for (i = 0; i < n; i++) {
gn = sk_GENERAL_NAME_value(alt, i);
if (gn->type != GEN_IPADD)
continue;
r = -1;
v = (char *)ASN1_STRING_data(gn->d.ia5);
l = ASN1_STRING_length(gn->d.ia5);
if (((family == AF_INET && l == sizeof(struct in_addr)) || (family == AF_INET6 && l == sizeof(struct in6_addr)))
&& !memcmp(v, &addr, l)) {
r = 1;
break;
}
}
GENERAL_NAMES_free(alt);
return r;
}
static int subjectaltnameregexp(X509 *cert, int type, char *exact, regex_t *regex) {
int loc, i, l, n, r = 0;
char *s, *v;
X509_EXTENSION *ex;
STACK_OF(GENERAL_NAME) *alt;
GENERAL_NAME *gn;
debug(DBG_DBG, "subjectaltnameregexp");
loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
if (loc < 0)
return