1 /* Copyright (C) 2011 NORDUnet A/S
2 * See LICENSE for information about licensing.
5 #include <stdio.h> /* For sprintf(). */
7 #include <nettle/sha.h>
8 #include <nettle/hmac.h>
14 #include "radsecproxy.h"
20 _format_hash(const uint8_t *hash, size_t out_len, uint8_t *out)
24 for (ir = 0, iw = 0; iw <= out_len - 3; ir++, iw += 2)
25 sprintf((char *) out + iw, "%02x", hash[ir % SHA256_DIGEST_SIZE]);
29 _hash(const uint8_t *in,
35 struct sha256_ctx ctx;
36 uint8_t hash[SHA256_DIGEST_SIZE];
39 sha256_update(&ctx, strlen((char *) in), in);
40 sha256_digest(&ctx, sizeof(hash), hash);
41 _format_hash(hash, out_len, out);
44 struct hmac_sha256_ctx ctx;
45 uint8_t hash[SHA256_DIGEST_SIZE];
47 hmac_sha256_set_key(&ctx, strlen((char *) key), key);
48 hmac_sha256_update(&ctx, strlen((char *) in), in);
49 hmac_sha256_digest(&ctx, sizeof(hash), hash);
50 _format_hash(hash, out_len, out);
55 fticks_configure(struct options *options,
61 const char *reporting = (const char *) *reportingp;
62 const char *mac = (const char *) *macp;
64 if (reporting == NULL)
67 if (strcasecmp(reporting, "None") == 0)
68 options->fticks_reporting = RSP_FTICKS_REPORTING_NONE;
69 else if (strcasecmp(reporting, "Basic") == 0)
70 options->fticks_reporting = RSP_FTICKS_REPORTING_BASIC;
71 else if (strcasecmp(reporting, "Full") == 0)
72 options->fticks_reporting = RSP_FTICKS_REPORTING_FULL;
74 debugx(1, DBG_ERR, "config error: invalid FTicksReporting value: %s",
80 if (strcasecmp(mac, "Static") == 0)
81 options->fticks_mac = RSP_FTICKS_MAC_STATIC;
82 else if (strcasecmp(mac, "Original") == 0)
83 options->fticks_mac = RSP_FTICKS_MAC_ORIGINAL;
84 else if (strcasecmp(mac, "VendorHashed") == 0)
85 options->fticks_mac = RSP_FTICKS_MAC_VENDOR_HASHED;
86 else if (strcasecmp(mac, "VendorKeyHashed") == 0)
87 options->fticks_mac = RSP_FTICKS_MAC_VENDOR_KEY_HASHED;
88 else if (strcasecmp(mac, "FullyHashed") == 0)
89 options->fticks_mac = RSP_FTICKS_MAC_FULLY_HASHED;
90 else if (strcasecmp(mac, "FullyKeyHashed") == 0)
91 options->fticks_mac = RSP_FTICKS_MAC_FULLY_KEY_HASHED;
93 debugx(1, DBG_ERR, "config error: invalid FTicksMAC value: %s", mac);
99 && (options->fticks_mac == RSP_FTICKS_MAC_VENDOR_KEY_HASHED
100 || options->fticks_mac == RSP_FTICKS_MAC_FULLY_KEY_HASHED)) {
102 "config error: FTicksMAC %s requires an FTicksKey", mac);
103 options->fticks_mac = RSP_FTICKS_MAC_STATIC;
109 options->fticks_key = *keyp;
112 if (*reportingp != NULL) {
123 /** Hash the Ethernet MAC address in \a IN, keying a HMAC with \a KEY
124 unless \a KEY is NULL. If \a KEY is null \a IN is hashed with an
125 ordinary cryptographic hash function such as SHA-2.
127 \a IN and \a KEY are NULL terminated strings.
129 \a IN is supposed to be an Ethernet MAC address and is sanitised
130 by lowercasing it, removing all but [0-9a-f] and truncating it at
131 the first ';' found. The truncation is done because RADIUS
132 supposedly has a praxis of tacking on SSID to the MAC address in
133 Calling-Station-Id. */
135 fticks_hashmac(const uint8_t *in,
140 /* TODO: lowercase */
141 /* TODO: s/[!0-9a-f]//1 */
142 /* TODO: truncate after first ';', if any */
144 _hash(in, key, out_len, out);
148 fticks_log(const struct options *options,
149 const struct client *client,
150 const struct radmsg *msg,
151 const struct rqout *rqout)
153 uint8_t *username = NULL;
154 uint8_t *realm = NULL;
155 uint8_t visinst[8+40+1+1]; /* Room for 40 octets of VISINST. */
156 uint8_t *macin = NULL;
157 uint8_t macout[2*32+1]; /* Room for ASCII representation of SHA256. */
159 username = radattr2ascii(radmsg_gettype(rqout->rq->msg,
160 RAD_Attr_User_Name));
161 if (username != NULL) {
162 realm = (uint8_t *) strrchr((char *) username, '@');
167 realm = (uint8_t *) "";
169 memset(visinst, 0, sizeof(visinst));
170 if (options->fticks_reporting == RSP_FTICKS_REPORTING_FULL) {
171 snprintf((char *) visinst, sizeof(visinst), "VISINST=%s#",
175 memset(macout, 0, sizeof(macout));
176 if (options->fticks_mac == RSP_FTICKS_MAC_STATIC) {
177 strncpy((char *) macout, "undisclosed", sizeof(macout) - 1);
180 macin = radattr2ascii(radmsg_gettype(rqout->rq->msg,
181 RAD_Attr_Calling_Station_Id));
183 switch (options->fticks_mac)
185 case RSP_FTICKS_MAC_ORIGINAL:
186 memcpy(macout, macin, sizeof(macout));
188 case RSP_FTICKS_MAC_VENDOR_HASHED:
189 memcpy(macout, macin, 9);
190 fticks_hashmac(macin, NULL, sizeof(macout) - 9, macout + 9);
192 case RSP_FTICKS_MAC_VENDOR_KEY_HASHED:
193 memcpy(macout, macin, 9);
194 /* We are hashing the first nine octets too for easier
195 * correlation between vendor-key-hashed and
196 * fully-key-hashed log records. This opens up for a
197 * known plaintext attack on the key but the
198 * consequences of that is considered outweighed by
199 * the convenience gained. */
200 fticks_hashmac(macin, options->fticks_key,
201 sizeof(macout) - 9, macout + 9);
203 case RSP_FTICKS_MAC_FULLY_HASHED:
204 fticks_hashmac(macin, NULL, sizeof(macout), macout);
206 case RSP_FTICKS_MAC_FULLY_KEY_HASHED:
207 fticks_hashmac(macin, options->fticks_key, sizeof(macout),
211 debugx(2, DBG_ERR, "invalid fticks mac configuration: %d",
212 options->fticks_mac);
217 "F-TICKS/eduroam/1.0#REALM=%s#VISCOUNTRY=%s#%sCSI=%s#RESULT=%s#",
219 client->conf->fticks_viscountry,
222 msg->code == RAD_Access_Accept ? "OK" : "FAIL");
225 if (username != NULL)
229 /* Local Variables: */
230 /* c-file-style: "stroustrup" */