diff --git a/ChangeLog b/ChangeLog index a42cb59..3ab85d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,7 @@ Changes between 1.6.9 and the master branch - Reload TLS certificate CRLs on SIGHUP (RADSECPROXY-78). - Make use of SO_KEEPALIVE for tcp sockets (RADSECPROXY-12). - Optionally include the thread-id in log messages + - Allow hashing MAC addresses in the log (same as for F-Ticks) - radsecproxy-hash: allow MAC addresses to be passed on command line Misc: diff --git a/fticks.c b/fticks.c index 49a50fd..6123ca7 100644 --- a/fticks.c +++ b/fticks.c @@ -19,7 +19,7 @@ fticks_configure(struct options *options, /* Set defaults. */ options->fticks_reporting = RSP_FTICKS_REPORTING_NONE; - options->fticks_mac = RSP_FTICKS_MAC_VENDOR_KEY_HASHED; + options->fticks_mac = RSP_MAC_VENDOR_KEY_HASHED; if (reporting != NULL) { if (strcasecmp(reporting, "None") == 0) @@ -38,17 +38,17 @@ fticks_configure(struct options *options, if (mac != NULL) { if (strcasecmp(mac, "Static") == 0) - options->fticks_mac = RSP_FTICKS_MAC_STATIC; + options->fticks_mac = RSP_MAC_STATIC; else if (strcasecmp(mac, "Original") == 0) - options->fticks_mac = RSP_FTICKS_MAC_ORIGINAL; + options->fticks_mac = RSP_MAC_ORIGINAL; else if (strcasecmp(mac, "VendorHashed") == 0) - options->fticks_mac = RSP_FTICKS_MAC_VENDOR_HASHED; + options->fticks_mac = RSP_MAC_VENDOR_HASHED; else if (strcasecmp(mac, "VendorKeyHashed") == 0) - options->fticks_mac = RSP_FTICKS_MAC_VENDOR_KEY_HASHED; + options->fticks_mac = RSP_MAC_VENDOR_KEY_HASHED; else if (strcasecmp(mac, "FullyHashed") == 0) - options->fticks_mac = RSP_FTICKS_MAC_FULLY_HASHED; + options->fticks_mac = RSP_MAC_FULLY_HASHED; else if (strcasecmp(mac, "FullyKeyHashed") == 0) - options->fticks_mac = RSP_FTICKS_MAC_FULLY_KEY_HASHED; + options->fticks_mac = RSP_MAC_FULLY_KEY_HASHED; else { debugx(1, DBG_ERR, "config error: invalid FTicksMAC value: %s", mac); @@ -58,13 +58,13 @@ fticks_configure(struct options *options, if (*keyp != NULL) { options->fticks_key = *keyp; - if (options->fticks_mac != RSP_FTICKS_MAC_VENDOR_KEY_HASHED - && options->fticks_mac != RSP_FTICKS_MAC_FULLY_KEY_HASHED) + if (options->fticks_mac != RSP_MAC_VENDOR_KEY_HASHED + && options->fticks_mac != RSP_MAC_FULLY_KEY_HASHED) debugx(1, DBG_WARN, "config warning: FTicksKey not used"); } else if (options->fticks_reporting != RSP_FTICKS_REPORTING_NONE - && (options->fticks_mac == RSP_FTICKS_MAC_VENDOR_KEY_HASHED - || options->fticks_mac == RSP_FTICKS_MAC_FULLY_KEY_HASHED)) { + && (options->fticks_mac == RSP_MAC_VENDOR_KEY_HASHED + || options->fticks_mac == RSP_MAC_FULLY_KEY_HASHED)) { debugx(1, DBG_ERR, "config error: FTicksMAC values VendorKeyHashed and " "FullyKeyHashed require an FTicksKey"); @@ -117,7 +117,7 @@ fticks_log(const struct options *options, } memset(macout, 0, sizeof(macout)); - if (options->fticks_mac == RSP_FTICKS_MAC_STATIC) { + if (options->fticks_mac == RSP_MAC_STATIC) { strncpy((char *) macout, "undisclosed", sizeof(macout) - 1); } else { @@ -126,14 +126,14 @@ fticks_log(const struct options *options, if (macin) { switch (options->fticks_mac) { - case RSP_FTICKS_MAC_ORIGINAL: + case RSP_MAC_ORIGINAL: memcpy(macout, macin, sizeof(macout)); break; - case RSP_FTICKS_MAC_VENDOR_HASHED: + case RSP_MAC_VENDOR_HASHED: memcpy(macout, macin, 9); fticks_hashmac(macin, NULL, sizeof(macout) - 9, macout + 9); break; - case RSP_FTICKS_MAC_VENDOR_KEY_HASHED: + case RSP_MAC_VENDOR_KEY_HASHED: memcpy(macout, macin, 9); /* We are hashing the first nine octets too for easier * correlation between vendor-key-hashed and @@ -144,10 +144,10 @@ fticks_log(const struct options *options, fticks_hashmac(macin, options->fticks_key, sizeof(macout) - 9, macout + 9); break; - case RSP_FTICKS_MAC_FULLY_HASHED: + case RSP_MAC_FULLY_HASHED: fticks_hashmac(macin, NULL, sizeof(macout), macout); break; - case RSP_FTICKS_MAC_FULLY_KEY_HASHED: + case RSP_MAC_FULLY_KEY_HASHED: fticks_hashmac(macin, options->fticks_key, sizeof(macout), macout); break; diff --git a/radsecproxy.c b/radsecproxy.c index e94dfe6..bbbcb6f 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -69,6 +69,7 @@ #include "tls.h" #include "dtls.h" #include "fticks.h" +#include "fticks_hashmac.h" static struct options options; static struct list *clconfs, *srvconfs; @@ -1409,7 +1410,7 @@ int radsrv(struct request *rq) { rq->buf = NULL; if (!msg) { - debug(DBG_INFO, "radsrv: message validation failed, ignoring packet"); + debug(DBG_NOTICE, "radsrv: ignoring request from %s (%s), validation failed.", from->conf->name, addr2string(from->addr)); freerq(rq); return 0; } @@ -1568,7 +1569,7 @@ void replyh(struct server *server, unsigned char *buf) { struct rqout *rqout; int sublen, ttlres; unsigned char *subattrs; - uint8_t *username, *stationid, *replymsg; + uint8_t *username, *logusername, *stationid, *replymsg, *logstationid; struct radmsg *msg = NULL; struct tlv *attr; struct list_node *node; @@ -1591,7 +1592,7 @@ void replyh(struct server *server, unsigned char *buf) { free(buf); buf = NULL; if (!msg) { - debug(DBG_INFO, "replyh: message validation failed, ignoring packet"); + debug(DBG_NOTICE, "replyh: ignoring message from server %s, validation failed", server->conf->name); goto errunlock; } if (msg->code != RAD_Access_Accept && msg->code != RAD_Access_Reject && msg->code != RAD_Access_Challenge @@ -1651,38 +1652,62 @@ void replyh(struct server *server, unsigned char *buf) { 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) { - if (replymsg) { - debug(DBG_NOTICE, - "%s for user %s stationid %s from %s (%s) to %s (%s)", - radmsgtype2string(msg->code), username, stationid, - 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), username, stationid, - server->conf->name, from->conf->name, - addr2string(from->addr)); - free(stationid); - } else { - if (replymsg) { - debug(DBG_NOTICE, "%s for user %s from %s (%s) to %s (%s)", - radmsgtype2string(msg->code), username, - 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), username, - server->conf->name, from->conf->name, - addr2string(from->addr)); - } - free(username); - } + 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); + } } if (msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject) @@ -3100,6 +3125,8 @@ void getmainconfig(const char *configfile) { struct gconffile *cfs; char **listenargs[RAD_PROTOCOUNT]; char *sourcearg[RAD_PROTOCOUNT]; + char *log_mac_str = NULL; + char *log_key_str = NULL; uint8_t *fticks_reporting_str = NULL; uint8_t *fticks_mac_str = NULL; uint8_t *fticks_key_str = NULL; @@ -3109,6 +3136,7 @@ void getmainconfig(const char *configfile) { memset(&options, 0, sizeof(options)); memset(&listenargs, 0, sizeof(listenargs)); memset(&sourcearg, 0, sizeof(sourcearg)); + options.logfullusername = 1; clconfs = list_create(); if (!clconfs) @@ -3150,6 +3178,9 @@ void getmainconfig(const char *configfile) { "LogLevel", CONF_LINT, &loglevel, "LogDestination", CONF_STR, &options.logdestination, "LogThreadId", CONF_BLN, &options.logtid, + "LogMAC", CONF_STR, &log_mac_str, + "LogKey", CONF_STR, &log_key_str, + "LogFullUsername", CONF_BLN, &options.logfullusername, "LoopPrevention", CONF_BLN, &options.loopprevention, "Client", CONF_CBK, confclient_cb, NULL, "Server", CONF_CBK, confserver_cb, NULL, @@ -3174,6 +3205,32 @@ void getmainconfig(const char *configfile) { debugx(1, DBG_ERR, "error in %s, value of option LogLevel is %d, must be 1, 2, 3, 4 or 5", configfile, loglevel); options.loglevel = (uint8_t)loglevel; } + if (log_mac_str != NULL) { + if (strcasecmp(log_mac_str, "Static") == 0) + options.log_mac = RSP_MAC_STATIC; + else if (strcasecmp(log_mac_str, "Original") == 0) + options.log_mac = RSP_MAC_ORIGINAL; + else if (strcasecmp(log_mac_str, "VendorHashed") == 0) + options.log_mac = RSP_MAC_VENDOR_HASHED; + else if (strcasecmp(log_mac_str, "VendorKeyHashed") == 0) + options.log_mac = RSP_MAC_VENDOR_KEY_HASHED; + else if (strcasecmp(log_mac_str, "FullyHashed") == 0) + options.log_mac = RSP_MAC_FULLY_HASHED; + else if (strcasecmp(log_mac_str, "FullyKeyHashed") == 0) + options.log_mac = RSP_MAC_FULLY_KEY_HASHED; + else { + debugx(1, DBG_ERR, "config error: invalid LogMAC value: %s", log_mac_str); + } + if (log_key_str != NULL) { + options.log_key = (uint8_t *)log_key_str; + } else if ((options.log_mac == RSP_MAC_VENDOR_KEY_HASHED + || options.log_mac == RSP_MAC_FULLY_KEY_HASHED)) { + debugx(1, DBG_ERR, "config error: LogMAC %s requires LogKey to be set.", log_mac_str); + } + } else { + options.log_mac = RSP_MAC_ORIGINAL; + } + if (addttl != LONG_MIN) { if (addttl < 1 || addttl > 255) debugx(1, DBG_ERR, "error in %s, value of option addTTL is %d, must be 1-255", configfile, addttl); @@ -3307,6 +3364,8 @@ 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)) diff --git a/radsecproxy.conf-example b/radsecproxy.conf-example index c97a772..b977d9a 100644 --- a/radsecproxy.conf-example +++ b/radsecproxy.conf-example @@ -38,32 +38,34 @@ # its matching client configuration block has to contain the # fticksVISCOUNTRY option. -# You can optionally specify FTicksMAC in order to determine if and +# You can optionally specify Log MAC and FTicksMAC in order to determine if and # how Calling-Station-Id (users Ethernet MAC address) is being logged. # Static -- Use a static string as a placeholder for -# Calling-Station-Id. -# Original -- Log Calling-Station-Id as-is. +# Calling-Station-Id in F-Ticks, of omit it in normal log. +# Original -- Log Calling-Station-Id as-is. This is the default for log. # VendorHashed -- Keep first three segments as-is, hash the rest. -# VendorKeyHashed -- Like VendorHashed but salt with F-Ticks-Key. This -# is the default. +# VendorKeyHashed -- Like VendorHashed but salt with F-Ticks-Key or Log-key +# respectively. This is the default for F-Ticks. # FullyHashed -- Hash the entire string. # FullyKeyHashed -- Like FullyHashed but salt with F-Ticks-Key. -# In order to use FTicksMAC with one of VendorKeyHashed or -# FullyKeyHashed, specify a key with FTicksKey. -# FTicksKey +# In order to use LogMAC or FTicksMAC with one of VendorKeyHashed or +# FullyKeyHashed, specify a key with LogKey or FTicksKey. +#LogKey +#FTicksKey -# Default F-Ticks configuration: +# Default Log andF-Ticks configuration: +#LogMAC Original #FTicksReporting None #FTicksMAC Static -# You can optionally specify FTicksSyslogFacility to use a dedicated +# You can optionally specify FTicksSyslogFacility to use a dedicated # syslog facility for F-Ticks messages. This allows for easier filtering # of F-Ticks messages. # F-Ticks messages are always logged using the log level LOG_DEBUG. # Note that specifying a file (using the file:/// prefix) is not supported. #FTicksSyslogFacility log_local1 -#FTicksSyslogFacility x-syslog:///log_local1 +#FTicksSyslogFacility x-syslog:///log_local1 # There is an option for doing some simple loop prevention. Note that # the LoopPrevention directive can be used in server blocks too, @@ -149,7 +151,7 @@ client 127.0.0.1 { # Might do rewriting of incoming messages using rewrite block example # rewriteIn example # Can also do rewriting of outgoing messages -# rewriteOut example +# rewriteOut example } client 127.0.0.1 { type tcp @@ -170,7 +172,7 @@ server 127.0.0.1 { # Might do rewriting of incoming messages using rewrite block example # rewriteIn example # Can also do rewriting of outgoing messages -# rewriteOut example +# rewriteOut example # Might override loop prevention here too: # LoopPrevention off } diff --git a/radsecproxy.conf.5.xml b/radsecproxy.conf.5.xml index 4bece35..3f6937d 100644 --- a/radsecproxy.conf.5.xml +++ b/radsecproxy.conf.5.xml @@ -186,6 +186,47 @@ blocktype name { + + LogFullUsername + + + This can be set to off to only log the + realm in Access-Accept/Reject log messages (for privacy). + + + + + LogMAC + + + The LogMAC option can be used to control if and how + Calling-Station-Id (the users Ethernet MAC address) is + being logged. It can be set to one of + Static, Original, + VendorHashed, + VendorKeyHashed, + FullyHashed or + FullyKeyHashed. + The default value for LogMAC is Original. + + + See radsecproxy.conf-example for details. + + + + + + LogKey + + + The LogKey option is used to specify the key to use + when producing HMAC's as an effect of specifying + VendorKeyHashed or FullyKeyHashed for the LogMAC + option. + + + + FTicksReporting @@ -210,30 +251,17 @@ blocktype name { FTicksMAC - The FTicksMAC option can be used to control if and how - Calling-Station-Id (the users Ethernet MAC address) is - being logged. It can be set to one of - Static, Original, - VendorHashed, - VendorKeyHashed, - FullyHashed or - FullyKeyHashed. - - - The default value for FTicksMAC is - VendorKeyHashed. This means that - FTicksKey has to be set. - + The FTicksMAC option has the same function as LogMAC for FTicks. + The default for FTicksMAC is VendorKeyHashed which + needs FTicksKey to be set. + + Before chosing any of Original, FullyHashed or VendorHashed, consider the implications for user privacy when MAC addresses are collected. How will the logs be stored, transferred and accessed? - - - See radsecproxy.conf-example for details. - @@ -241,10 +269,7 @@ blocktype name { FTicksKey - The FTicksKey option is used to specify the key to use - when producing HMAC's as an effect of specifying - VendorKeyHashed or FullyKeyHashed for the FTicksMAC - option. + The FTicksKey option has the same function as LogKey for Fticks. diff --git a/radsecproxy.h b/radsecproxy.h index eb4c33f..64a4090 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -50,13 +50,13 @@ enum rsp_fticks_reporting_type { RSP_FTICKS_REPORTING_FULL }; -enum rsp_fticks_mac_type { - RSP_FTICKS_MAC_STATIC = 0, - RSP_FTICKS_MAC_ORIGINAL, - RSP_FTICKS_MAC_VENDOR_HASHED, - RSP_FTICKS_MAC_VENDOR_KEY_HASHED, /* Default. */ - RSP_FTICKS_MAC_FULLY_HASHED, - RSP_FTICKS_MAC_FULLY_KEY_HASHED +enum rsp_mac_type { + RSP_MAC_STATIC = 0, + RSP_MAC_ORIGINAL, + RSP_MAC_VENDOR_HASHED, + RSP_MAC_VENDOR_KEY_HASHED, /* Default. */ + RSP_MAC_FULLY_HASHED, + RSP_MAC_FULLY_KEY_HASHED }; enum rsp_server_state { @@ -76,9 +76,12 @@ struct options { uint8_t addttl; uint8_t loglevel; uint8_t logtid; + uint8_t logfullusername; uint8_t loopprevention; + enum rsp_mac_type log_mac; + uint8_t *log_key; enum rsp_fticks_reporting_type fticks_reporting; - enum rsp_fticks_mac_type fticks_mac; + enum rsp_mac_type fticks_mac; uint8_t *fticks_key; uint8_t ipv4only; uint8_t ipv6only; diff --git a/tlscommon.c b/tlscommon.c index 7ffef3f..11b907c 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -377,6 +377,8 @@ void tlsreloadcrls() { struct hash_entry *entry; struct timeval now; + debug (DBG_NOTICE, "reloading CRLs"); + gettimeofday(&now, NULL); for (entry = hash_first(tlsconfs); entry; entry = hash_next(entry)) {