diff --git a/fticks.c b/fticks.c index 6123ca7..a7bfd57 100644 --- a/fticks.c +++ b/fticks.c @@ -87,7 +87,7 @@ void fticks_log(const struct options *options, const struct client *client, const struct radmsg *msg, - const struct rqout *rqout) + const struct request *rq) { uint8_t *username = NULL; uint8_t *realm = NULL; @@ -95,7 +95,7 @@ fticks_log(const struct options *options, uint8_t *macin = NULL; uint8_t macout[2*32+1]; /* Room for ASCII representation of SHA256. */ - username = radattr2ascii(radmsg_gettype(rqout->rq->msg, + username = radattr2ascii(radmsg_gettype(rq->msg, RAD_Attr_User_Name)); if (username != NULL) { realm = (uint8_t *) strrchr((char *) username, '@'); @@ -121,7 +121,7 @@ fticks_log(const struct options *options, strncpy((char *) macout, "undisclosed", sizeof(macout) - 1); } else { - macin = radattr2ascii(radmsg_gettype(rqout->rq->msg, + macin = radattr2ascii(radmsg_gettype(rq->msg, RAD_Attr_Calling_Station_Id)); if (macin) { switch (options->fticks_mac) diff --git a/fticks.h b/fticks.h index 5786d12..c2903c2 100644 --- a/fticks.h +++ b/fticks.h @@ -8,7 +8,7 @@ int fticks_configure(struct options *options, void fticks_log(const struct options *options, const struct client *client, const struct radmsg *msg, - const struct rqout *rqout); + const struct request *rq); /* Local Variables: */ /* c-file-style: "stroustrup" */ diff --git a/radsecproxy.c b/radsecproxy.c index bbbcb6f..975db21 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -1219,18 +1219,76 @@ uint8_t *radattr2ascii(struct tlv *attr) { return a; } -void acclog(struct radmsg *msg, struct client *from) { - struct tlv *attr; - uint8_t *username; +void replylog(struct radmsg *msg, struct server *server, struct request *rq) { + uint8_t *username, *logusername, *stationid, *logstationid, *replymsg; + char *servername; - attr = radmsg_gettype(msg, RAD_Attr_User_Name); - if (attr && (username = radattr2ascii(attr))) { - debug(DBG_INFO, "acclog: %s (id %d) from client %s (%s) with username: %s", radmsgtype2string(msg->code), msg->id, from->conf->name, addr2string(from->addr), username); - free(username); - } else { - debug(DBG_INFO, "acclog: %s (id %d) from client %s (%s) without username attribute", radmsgtype2string(msg->code), msg->id, from->conf->name, addr2string(from->addr)); + servername = server ? server->conf->name : "_self_"; + + if (msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject || msg->code == RAD_Accounting_Response) { + username = radattr2ascii(radmsg_gettype(rq->msg, RAD_Attr_User_Name)); + if (username) { + if (options.logfullusername) { + logusername = username; + } else { + logusername = (uint8_t *)strchr((char *)username, '@'); + } + stationid = radattr2ascii(radmsg_gettype(rq->msg, RAD_Attr_Calling_Station_Id)); + replymsg = radattr2ascii(radmsg_gettype(msg, RAD_Attr_Reply_Message)); + if (stationid && options.log_mac != RSP_MAC_STATIC) { + logstationid = calloc(64, sizeof(char)); + switch (options.log_mac) { + case RSP_MAC_VENDOR_HASHED: + case RSP_MAC_VENDOR_KEY_HASHED: + memcpy(logstationid, stationid, 9); + fticks_hashmac(stationid, options.log_mac == RSP_MAC_VENDOR_KEY_HASHED ? + options.log_key : NULL, 32, logstationid+9); + break; + case RSP_MAC_FULLY_HASHED: + case RSP_MAC_FULLY_KEY_HASHED: + fticks_hashmac(stationid, options.log_mac == RSP_MAC_FULLY_KEY_HASHED ? + options.log_key : NULL, 32, logstationid); + break; + case RSP_MAC_ORIGINAL: + default: + strncpy((char *)logstationid, (char *)stationid, 64-1); + } + if (replymsg) { + debug(DBG_NOTICE, "%s for user %s stationid %s from %s (%s) to %s (%s)", + radmsgtype2string(msg->code), logusername, logstationid, + servername, replymsg, rq->from->conf->name, + addr2string(rq->from->addr)); + free(replymsg); + } else { + debug(DBG_NOTICE, "%s for user %s stationid %s from %s to %s (%s)", + radmsgtype2string(msg->code), logusername, logstationid, + servername, rq->from->conf->name, + addr2string(rq->from->addr)); + } + free(stationid); + if (options.log_mac != RSP_MAC_STATIC && + options.log_mac != RSP_MAC_ORIGINAL) + free(logstationid); + } else { + if (replymsg) { + debug(DBG_NOTICE, "%s for user %s from %s (%s) to %s (%s)", + radmsgtype2string(msg->code), logusername, + servername, replymsg, rq->from->conf->name, + addr2string(rq->from->addr)); + free(replymsg); + } else + debug(DBG_NOTICE, "%s for user %s from %s to %s (%s)", + radmsgtype2string(msg->code), logusername, + servername, rq->from->conf->name, + addr2string(rq->from->addr)); + } + free(username); + } else { + debug(DBG_NOTICE, "%s (response to %s) from %s to %s (%s)", radmsgtype2string(msg->code), + radmsgtype2string(rq->msg->code), servername, + rq->from->conf->name, addr2string(rq->from->addr)); + } } - debug(DBG_INFO, "acclog: sending %s (id %d) to %s (%s)", radmsgtype2string(RAD_Accounting_Response), msg->id, from->conf->name, addr2string(from->addr)); } void respond(struct request *rq, uint8_t code, char *message, @@ -1260,9 +1318,11 @@ void respond(struct request *rq, uint8_t code, char *message, } } + replylog(msg, NULL, rq); + debug(DBG_DBG, "respond: sending %s (id %d) to %s (%s)", radmsgtype2string(msg->code), msg->id, rq->from->conf->name, addr2string(rq->from->addr)); + radmsg_free(rq->msg); rq->msg = msg; - debug(DBG_DBG, "respond: sending %s to %s (%s)", radmsgtype2string(msg->code), rq->from->conf->name, addr2string(rq->from->addr)); sendreply(newrqref(rq)); } @@ -1448,7 +1508,6 @@ int radsrv(struct request *rq) { attr = radmsg_gettype(msg, RAD_Attr_User_Name); if (!attr) { if (msg->code == RAD_Accounting_Request) { - acclog(msg, from); respond(rq, RAD_Accounting_Response, NULL, 1); } else debug(DBG_INFO, "radsrv: ignoring access request, no username attribute"); @@ -1477,7 +1536,6 @@ int radsrv(struct request *rq) { debug(DBG_INFO, "radsrv: sending %s (id %d) to %s (%s) for %s", radmsgtype2string(RAD_Access_Reject), msg->id, from->conf->name, addr2string(from->addr), userascii); respond(rq, RAD_Access_Reject, realm->message, 1); } else if (realm->accresp && msg->code == RAD_Accounting_Request) { - acclog(msg, from); respond(rq, RAD_Accounting_Response, NULL, 1); } goto exit; @@ -1569,7 +1627,6 @@ void replyh(struct server *server, unsigned char *buf) { struct rqout *rqout; int sublen, ttlres; unsigned char *subattrs; - uint8_t *username, *logusername, *stationid, *replymsg, *logstationid; struct radmsg *msg = NULL; struct tlv *attr; struct list_node *node; @@ -1606,7 +1663,7 @@ void replyh(struct server *server, unsigned char *buf) { if (rqout->rq->msg->code == RAD_Status_Server) { freerqoutdata(rqout); - debug(DBG_DBG, "replyh: got status server response from %s", server->conf->name); + debug(DBG_NOTICE, "replyh: got status server response from %s", server->conf->name); goto errunlock; } @@ -1649,70 +1706,11 @@ void replyh(struct server *server, unsigned char *buf) { goto errunlock; } - if (msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject || msg->code == RAD_Accounting_Response) { - username = radattr2ascii(radmsg_gettype(rqout->rq->msg, RAD_Attr_User_Name)); - if (username) { - if (options.logfullusername) { - logusername = username; - } else { - logusername = (uint8_t *)strchr((char *)username, '@'); - } - stationid = radattr2ascii(radmsg_gettype(rqout->rq->msg, RAD_Attr_Calling_Station_Id)); - replymsg = radattr2ascii(radmsg_gettype(msg, RAD_Attr_Reply_Message)); - if (stationid && options.log_mac != RSP_MAC_STATIC) { - logstationid = calloc(64, sizeof(char)); - switch (options.log_mac) { - case RSP_MAC_VENDOR_HASHED: - case RSP_MAC_VENDOR_KEY_HASHED: - memcpy(logstationid, stationid, 9); - fticks_hashmac(stationid, options.log_mac == RSP_MAC_VENDOR_KEY_HASHED ? - options.log_key : NULL, 32, logstationid+9); - break; - case RSP_MAC_FULLY_HASHED: - case RSP_MAC_FULLY_KEY_HASHED: - fticks_hashmac(stationid, options.log_mac == RSP_MAC_FULLY_KEY_HASHED ? - options.log_key : NULL, 32, logstationid); - break; - case RSP_MAC_ORIGINAL: - default: - strncpy((char *)logstationid, (char *)stationid, 64-1); - } - if (replymsg) { - debug(DBG_NOTICE, "%s for user %s stationid %s from %s (%s) to %s (%s)", - radmsgtype2string(msg->code), logusername, logstationid, - server->conf->name, replymsg, from->conf->name, - addr2string(from->addr)); - free(replymsg); - } else { - debug(DBG_NOTICE, "%s for user %s stationid %s from %s to %s (%s)", - radmsgtype2string(msg->code), logusername, logstationid, - server->conf->name, from->conf->name, - addr2string(from->addr)); - } - free(stationid); - if (options.log_mac != RSP_MAC_STATIC && - options.log_mac != RSP_MAC_ORIGINAL) - free(logstationid); - } else { - if (replymsg) { - debug(DBG_NOTICE, "%s for user %s from %s (%s) to %s (%s)", - radmsgtype2string(msg->code), logusername, - server->conf->name, replymsg, from->conf->name, - addr2string(from->addr)); - free(replymsg); - } else - debug(DBG_NOTICE, "%s for user %s from %s to %s (%s)", - radmsgtype2string(msg->code), logusername, - server->conf->name, from->conf->name, - addr2string(from->addr)); - } - free(username); - } - } + replylog(msg, server, rqout->rq); if (msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject) - if (options.fticks_reporting && from->conf->fticks_viscountry != NULL) - fticks_log(&options, from, msg, rqout); + if (options.fticks_reporting && from->conf->fticks_viscountry != NULL) + fticks_log(&options, from, msg, rqout->rq); msg->id = (char)rqout->rq->rqid; memcpy(msg->auth, rqout->rq->rqauth, 16); @@ -3364,8 +3362,6 @@ int radsecproxy_main(int argc, char **argv) { debug_init("radsecproxy"); debug_set_level(DEBUG_LEVEL); - debug (DBG_NOTICE, "radsecproxy %s starting.", PACKAGE_VERSION); - if (pthread_attr_init(&pthread_attr)) debugx(1, DBG_ERR, "pthread_attr_init failed"); if (pthread_attr_setstacksize(&pthread_attr, PTHREAD_STACK_SIZE)) @@ -3407,6 +3403,8 @@ int radsecproxy_main(int argc, char **argv) { if (options.logtid) debug_tid_on(); + debug(DBG_NOTICE, "radsecproxy %s starting.", PACKAGE_VERSION); + if (!list_first(clconfs)) debugx(1, DBG_ERR, "No clients configured, nothing to do, exiting"); if (!list_first(realms)) diff --git a/tlscommon.c b/tlscommon.c index 11b907c..fab629c 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -3,6 +3,8 @@ /* See LICENSE for licensing information. */ #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) +#define _GNU_SOURCE +#include #include #include #include @@ -455,7 +457,7 @@ static int subjectaltnameaddr(X509 *cert, int family, struct in6_addr *addr) { static int subjectaltnameregexp(X509 *cert, int type, char *exact, regex_t *regex) { int loc, i, l, n, r = 0; - char *s, *v; + char *s, *v, *fail = NULL, *tmp; X509_EXTENSION *ex; STACK_OF(GENERAL_NAME) *alt; GENERAL_NAME *gn; @@ -493,16 +495,24 @@ static int subjectaltnameregexp(X509 *cert, int type, char *exact, regex_t *reg debug(DBG_ERR, "malloc failed"); continue; } - if (regexec(regex, s, 0, NULL, 0)) { - free(s); - continue; + debug(DBG_DBG, "subjectaltnameregex: matching %s", s); + if (regexec(regex, s, 0, NULL, 0)) { + tmp = fail; + asprintf(&fail, "%s%s%s", tmp ? tmp : "", tmp ? ", " : "", s); + free(tmp); + free(s); + continue; } free(s); } r = 1; break; } + if (r!=1) + debug(DBG_WARN, "subjectaltnameregex: no matching Subject Alt Name %s found! (%s)", + type == GEN_DNS ? "DNS" : "URI", fail); GENERAL_NAMES_free(alt); + free(fail); return r; } @@ -585,28 +595,34 @@ int certnamecheck(X509 *cert, struct list *hostports) { } int verifyconfcert(X509 *cert, struct clsrvconf *conf) { + char *subject; + int ok = 1; + + subject = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); + debug(DBG_DBG, "verifyconfcert: verify certificate for host %s, subject %s", conf->name, subject); if (conf->certnamecheck) { - if (!certnamecheck(cert, conf->hostports)) { - debug(DBG_WARN, "verifyconfcert: certificate name check failed"); - return 0; - } - debug(DBG_WARN, "verifyconfcert: certificate name check ok"); + debug(DBG_DBG, "verifyconfcert: verify hostname"); + if (!certnamecheck(cert, conf->hostports)) { + debug(DBG_DBG, "verifyconfcert: certificate name check failed for host %s", conf->name); + ok = 0; + } } 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"); + debug(DBG_DBG, "verifyconfcert: matching CN regex %s", conf->matchcertattr); + if (cnregexp(cert, NULL, conf->certcnregex) < 1) { + debug(DBG_WARN, "verifyconfcert: CN not matching regex for host %s (%s)", conf->name, subject); + ok = 0; + } } 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"); + debug(DBG_DBG, "verifyconfcert: matching subjectaltname URI regex %s", conf->matchcertattr); + if (subjectaltnameregexp(cert, GEN_URI, NULL, conf->certuriregex) < 1) { + debug(DBG_WARN, "verifyconfcert: subjectaltname URI not matching regex for host %s (%s)", conf->name, subject); + ok = 0; + } } - return 1; + free(subject); + return ok; } int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {