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 (i = 0; i < out_len / 2; i++)
25 sprintf((char *) out + i*2, "%02x", hash[i % 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 unsigned char *username = NULL;
150 unsigned char *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 = (unsigned char *) strrchr((char *) username, '@');
162 realm = (unsigned char *) "";
165 memset(visinst, 0, sizeof(visinst));
166 if (options->fticks_reporting == RSP_FTICKS_REPORTING_FULL)
167 snprintf((char *) visinst, sizeof(visinst), "VISINST=%s#",
170 #define BOGUS_MAC "00:00:00:00:00:00" /* FIXME: Is there a standard
171 * for bogus MAC addresses? */
172 memset(macout, 0, sizeof(macout));
173 strncpy((char *) macout, BOGUS_MAC, sizeof(macout) - 1);
174 if (options->fticks_mac != RSP_FTICKS_MAC_STATIC) {
175 macin = radattr2ascii(radmsg_gettype(rqout->rq->msg,
176 RAD_Attr_Calling_Station_Id));
180 macin = (uint8_t *) strdup(BOGUS_MAC);
181 #endif /* RS_TESTING */
183 switch (options->fticks_mac)
185 case RSP_FTICKS_MAC_STATIC:
186 memcpy(macout, BOGUS_MAC, sizeof(BOGUS_MAC));
188 case RSP_FTICKS_MAC_ORIGINAL:
189 memcpy(macout, macin, sizeof(macout));
191 case RSP_FTICKS_MAC_VENDOR_HASHED:
192 fticks_hashmac(macin + 3, NULL, sizeof(macout), macout);
194 case RSP_FTICKS_MAC_VENDOR_KEY_HASHED:
195 fticks_hashmac(macin + 3, options->fticks_key, sizeof(macout),
198 case RSP_FTICKS_MAC_FULLY_HASHED:
199 fticks_hashmac(macin, NULL, sizeof(macout), macout);
201 case RSP_FTICKS_MAC_FULLY_KEY_HASHED:
202 fticks_hashmac(macin, options->fticks_key, sizeof(macout), macout);
205 debugx(2, DBG_ERR, "invalid fticks mac configuration: %d",
206 options->fticks_mac);
209 "F-TICKS/eduroam/1.0#REALM=%s#VISCOUNTRY=%s#%sCSI=%s#RESULT=%s#",
211 client->conf->fticks_viscountry,
214 msg->code == RAD_Access_Accept ? "OK" : "FAIL");
217 if (username != NULL)
221 /* Local Variables: */
222 /* c-file-style: "stroustrup" */