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