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 MAC in \a IN, keying with \a KEY if it's not NULL.
125 \a IN and \a KEY are NULL terminated strings.
127 \a IN is sanitised by lowercasing it, removing all but [0-9a-f]
128 and truncating it at first ';' (due to RADIUS praxis with tacking
129 on SSID to MAC in Calling-Station-Id). */
131 fticks_hashmac(const uint8_t *in,
136 /* TODO: lowercase */
137 /* TODO: s/[!0-9a-f]//1 */
138 /* TODO: truncate after first ';', if any */
140 hash(in, key, out_len, out);
144 fticks_log(const struct options *options,
145 const struct client *client,
146 const struct radmsg *msg,
147 const struct rqout *rqout)
149 uint8_t *username = NULL;
150 uint8_t *realm = NULL;
151 uint8_t visinst[8+40+1+1]; /* Room for 40 octets of VISINST. */
152 uint8_t *macin = NULL;
153 uint8_t macout[2*32+1]; /* Room for ASCII representation of SHA256. */
155 username = radattr2ascii(radmsg_gettype(rqout->rq->msg,
156 RAD_Attr_User_Name));
157 if (username != NULL) {
158 realm = (uint8_t *) strrchr((char *) username, '@');
163 realm = (uint8_t *) "";
165 memset(visinst, 0, sizeof(visinst));
166 if (options->fticks_reporting == RSP_FTICKS_REPORTING_FULL) {
167 snprintf((char *) visinst, sizeof(visinst), "VISINST=%s#",
171 memset(macout, 0, sizeof(macout));
172 if (options->fticks_mac == RSP_FTICKS_MAC_STATIC) {
173 strncpy((char *) macout, "undisclosed", sizeof(macout) - 1);
176 macin = radattr2ascii(radmsg_gettype(rqout->rq->msg,
177 RAD_Attr_Calling_Station_Id));
179 switch (options->fticks_mac)
181 case RSP_FTICKS_MAC_ORIGINAL:
182 memcpy(macout, macin, sizeof(macout));
184 case RSP_FTICKS_MAC_VENDOR_HASHED:
185 memcpy(macout, macin, 9);
186 fticks_hashmac(macin, NULL, sizeof(macout) - 9, macout + 9);
188 case RSP_FTICKS_MAC_VENDOR_KEY_HASHED:
189 memcpy(macout, macin, 9);
190 /* We are hashing the first nine octets too for easier
191 * correlation between vendor-key-hashed and
192 * fully-key-hashed log records. This opens up for a
193 * known plaintext attack on the key but the
194 * consequences of that is considered outweighed by
195 * the convenience gained. */
196 fticks_hashmac(macin, options->fticks_key,
197 sizeof(macout) - 9, macout + 9);
199 case RSP_FTICKS_MAC_FULLY_HASHED:
200 fticks_hashmac(macin, NULL, sizeof(macout), macout);
202 case RSP_FTICKS_MAC_FULLY_KEY_HASHED:
203 fticks_hashmac(macin, options->fticks_key, sizeof(macout),
207 debugx(2, DBG_ERR, "invalid fticks mac configuration: %d",
208 options->fticks_mac);
213 "F-TICKS/eduroam/1.0#REALM=%s#VISCOUNTRY=%s#%sCSI=%s#RESULT=%s#",
215 client->conf->fticks_viscountry,
218 msg->code == RAD_Access_Accept ? "OK" : "FAIL");
221 if (username != NULL)
225 /* Local Variables: */
226 /* c-file-style: "stroustrup" */