a04f49d62e1732b58e37bd0430b2812e0fad0acd
[radsecproxy.git] / fticks.c
1 /* Copyright (c) 2006-2009, Stig Venaas, UNINETT AS.
2  * Copyright (c) 2010, UNINETT AS, NORDUnet A/S.
3  * Copyright (c) 2010-2012, NORDUnet A/S. */
4 /* See LICENSE for licensing information. */
5
6 #include "radsecproxy.h"
7 #include "debug.h"
8 #include "fticks.h"
9 #include "fticks_hashmac.h"
10
11 int
12 fticks_configure(struct options *options,
13                  uint8_t **reportingp,
14                  uint8_t **macp,
15                  uint8_t **keyp)
16 {
17     int r = 0;
18     const char *reporting = (const char *) *reportingp;
19     const char *mac = (const char *) *macp;
20
21     /* Set defaults.  */
22     options->fticks_reporting = RSP_FTICKS_REPORTING_NONE;
23     options->fticks_mac = RSP_FTICKS_MAC_VENDOR_KEY_HASHED;
24
25     if (reporting != NULL) {
26         if (strcasecmp(reporting, "None") == 0)
27             options->fticks_reporting = RSP_FTICKS_REPORTING_NONE;
28         else if (strcasecmp(reporting, "Basic") == 0)
29             options->fticks_reporting = RSP_FTICKS_REPORTING_BASIC;
30         else if (strcasecmp(reporting, "Full") == 0)
31             options->fticks_reporting = RSP_FTICKS_REPORTING_FULL;
32         else {
33             debugx(1, DBG_ERR,
34                    "config error: invalid FTicksReporting value: %s",
35                    reporting);
36             r = 1;
37         }
38     }
39
40     if (mac != NULL) {
41         if (strcasecmp(mac, "Static") == 0)
42             options->fticks_mac = RSP_FTICKS_MAC_STATIC;
43         else if (strcasecmp(mac, "Original") == 0)
44             options->fticks_mac = RSP_FTICKS_MAC_ORIGINAL;
45         else if (strcasecmp(mac, "VendorHashed") == 0)
46             options->fticks_mac = RSP_FTICKS_MAC_VENDOR_HASHED;
47         else if (strcasecmp(mac, "VendorKeyHashed") == 0)
48             options->fticks_mac = RSP_FTICKS_MAC_VENDOR_KEY_HASHED;
49         else if (strcasecmp(mac, "FullyHashed") == 0)
50             options->fticks_mac = RSP_FTICKS_MAC_FULLY_HASHED;
51         else if (strcasecmp(mac, "FullyKeyHashed") == 0)
52             options->fticks_mac = RSP_FTICKS_MAC_FULLY_KEY_HASHED;
53         else {
54             debugx(1, DBG_ERR,
55                    "config error: invalid FTicksMAC value: %s", mac);
56             r = 1;
57         }
58     }
59
60     if (*keyp != NULL) {
61         options->fticks_key = *keyp;
62         if (options->fticks_mac != RSP_FTICKS_MAC_VENDOR_KEY_HASHED
63             && options->fticks_mac != RSP_FTICKS_MAC_FULLY_KEY_HASHED)
64             debugx(1, DBG_WARN, "config warning: FTicksKey not used");
65     }
66     else if (options->fticks_reporting != RSP_FTICKS_REPORTING_NONE
67              && (options->fticks_mac == RSP_FTICKS_MAC_VENDOR_KEY_HASHED
68                  || options->fticks_mac == RSP_FTICKS_MAC_FULLY_KEY_HASHED)) {
69         debugx(1, DBG_ERR,
70                "config error: FTicksMAC values VendorKeyHashed and "
71                "FullyKeyHashed require an FTicksKey");
72         options->fticks_reporting = RSP_FTICKS_REPORTING_NONE;
73         r = 1;
74     }
75
76     if (*reportingp != NULL) {
77         free(*reportingp);
78         *reportingp = NULL;
79     }
80     if (*macp != NULL) {
81         free(*macp);
82         *macp = NULL;
83     }
84     return r;
85 }
86
87 void
88 fticks_log(const struct options *options,
89            const struct client *client,
90            const struct radmsg *msg,
91            const struct rqout *rqout)
92 {
93     uint8_t *username = NULL;
94     uint8_t *realm = NULL;
95     uint8_t visinst[8+40+1+1]; /* Room for 40 octets of VISINST.  */
96     uint8_t *macin = NULL;
97     uint8_t macout[2*32+1]; /* Room for ASCII representation of SHA256.  */
98
99     username = radattr2ascii(radmsg_gettype(rqout->rq->msg,
100                                             RAD_Attr_User_Name));
101     if (username != NULL) {
102         realm = (uint8_t *) strrchr((char *) username, '@');
103         if (realm != NULL)
104             realm++;
105     }
106     if (realm == NULL)
107         realm = (uint8_t *) "";
108
109     memset(visinst, 0, sizeof(visinst));
110     if (options->fticks_reporting == RSP_FTICKS_REPORTING_FULL) {
111         if (client->conf->fticks_visinst != NULL ) {
112             snprintf((char *) visinst, sizeof(visinst), "VISINST=%s#",
113                      client->conf->fticks_visinst);
114         } else {
115             snprintf((char *) visinst, sizeof(visinst), "VISINST=%s#",
116                      client->conf->name);
117         }
118     }
119
120     memset(macout, 0, sizeof(macout));
121     if (options->fticks_mac == RSP_FTICKS_MAC_STATIC) {
122         strncpy((char *) macout, "undisclosed", sizeof(macout) - 1);
123     }
124     else {
125         macin = radattr2ascii(radmsg_gettype(rqout->rq->msg,
126                                              RAD_Attr_Calling_Station_Id));
127         if (macin) {
128             switch (options->fticks_mac)
129             {
130             case RSP_FTICKS_MAC_ORIGINAL:
131                 memcpy(macout, macin, sizeof(macout));
132                 break;
133             case RSP_FTICKS_MAC_VENDOR_HASHED:
134                 memcpy(macout, macin, 9);
135                 fticks_hashmac(macin, NULL, sizeof(macout) - 9, macout + 9);
136                 break;
137             case RSP_FTICKS_MAC_VENDOR_KEY_HASHED:
138                 memcpy(macout, macin, 9);
139                 /* We are hashing the first nine octets too for easier
140                  * correlation between vendor-key-hashed and
141                  * fully-key-hashed log records.  This opens up for a
142                  * known plaintext attack on the key but the
143                  * consequences of that is considered outweighed by
144                  * the convenience gained.  */
145                 fticks_hashmac(macin, options->fticks_key,
146                                sizeof(macout) - 9, macout + 9);
147                 break;
148             case RSP_FTICKS_MAC_FULLY_HASHED:
149                 fticks_hashmac(macin, NULL, sizeof(macout), macout);
150                 break;
151             case RSP_FTICKS_MAC_FULLY_KEY_HASHED:
152                 fticks_hashmac(macin, options->fticks_key, sizeof(macout),
153                                macout);
154                 break;
155             default:
156                 debugx(2, DBG_ERR, "invalid fticks mac configuration: %d",
157                        options->fticks_mac);
158             }
159         }
160     }
161     fticks_debug(
162           "F-TICKS/eduroam/1.0#REALM=%s#VISCOUNTRY=%s#%sCSI=%s#RESULT=%s#",
163           realm,
164           client->conf->fticks_viscountry,
165           visinst,
166           macout,
167           msg->code == RAD_Access_Accept ? "OK" : "FAIL");
168     if (macin != NULL)
169         free(macin);
170     if (username != NULL)
171         free(username);
172 }
173
174 /* Local Variables: */
175 /* c-file-style: "stroustrup" */
176 /* End: */