Removed extra calls to HMAC_CTX_init()
[freeradius.git] / src / modules / rlm_wimax / rlm_wimax.c
index f468c27..8265802 100644 (file)
@@ -29,7 +29,73 @@ RCSID("$Id$")
 /*
  *     FIXME: Fix the build system to create definitions from names.
  */
-#define WIMAX2ATTR(x) ((24757 << 16) | (x))
+typedef struct rlm_wimax_t {
+       int     delete_mppe_keys;
+} rlm_wimax_t;
+
+/*
+ *     A mapping of configuration file names to internal variables.
+ *
+ *     Note that the string is dynamically allocated, so it MUST
+ *     be freed.  When the configuration file parse re-reads the string,
+ *     it free's the old one, and strdup's the new one, placing the pointer
+ *     to the strdup'd string into 'config.string'.  This gets around
+ *     buffer over-flows.
+ */
+static const CONF_PARSER module_config[] = {
+  { "delete_mppe_keys", PW_TYPE_BOOLEAN,
+    offsetof(rlm_wimax_t,delete_mppe_keys), NULL,   "no" },
+
+  { NULL, -1, 0, NULL, NULL }          /* end the list */
+};
+
+
+/*
+ *     Only free memory we allocated.  The strings allocated via
+ *     cf_section_parse() do not need to be freed.
+ */
+static int wimax_detach(void *instance)
+{
+       free(instance);
+       return 0;
+}
+
+/*
+ *     Do any per-module initialization that is separate to each
+ *     configured instance of the module.  e.g. set up connections
+ *     to external databases, read configuration files, set up
+ *     dictionary entries, etc.
+ *
+ *     If configuration information is given in the config section
+ *     that must be referenced in later calls, store a handle to it
+ *     in *instance otherwise put a null pointer there.
+ */
+static int wimax_instantiate(CONF_SECTION *conf, void **instance)
+{
+       rlm_wimax_t *inst;
+
+       /*
+        *      Set up a storage area for instance data
+        */
+       inst = rad_malloc(sizeof(*inst));
+       if (!inst) {
+               return -1;
+       }
+       memset(inst, 0, sizeof(*inst));
+
+       /*
+        *      If the configuration parameters can't be parsed, then
+        *      fail.
+        */
+       if (cf_section_parse(conf, inst, module_config) < 0) {
+               wimax_detach(inst);
+               return -1;
+       }
+
+       *instance = inst;
+
+       return 0;
+}
 
 /*
  *     Find the named user in this modules database.  Create the set
@@ -48,7 +114,7 @@ static int wimax_authorize(void *instance, REQUEST *request)
        /*
         *      Fix Calling-Station-Id.  Damn you, WiMAX!
         */
-       vp =  pairfind(request->packet->vps, PW_CALLING_STATION_ID);
+       vp =  pairfind(request->packet->vps, PW_CALLING_STATION_ID, 0);
        if (vp && (vp->length == 6)) {
                int i;
                uint8_t buffer[6];
@@ -99,8 +165,9 @@ static int wimax_accounting(void *instance, REQUEST *request)
 /*
  *     Generate the keys after the user has been authenticated.
  */
-static int wimax_postauth(UNUSED void *instance, REQUEST *request)
+static int wimax_postauth(void *instance, REQUEST *request)
 {
+       rlm_wimax_t *inst = instance;
        VALUE_PAIR *msk, *emsk, *vp;
        VALUE_PAIR *mn_nai, *ip, *fa_rk;
        HMAC_CTX hmac;
@@ -111,14 +178,29 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
        uint8_t mip_rk_1[EVP_MAX_MD_SIZE], mip_rk_2[EVP_MAX_MD_SIZE];
        uint8_t mip_rk[2 * EVP_MAX_MD_SIZE];
 
-       msk = pairfind(request->reply->vps, 1129);
-       emsk = pairfind(request->reply->vps, 1130);
+       msk = pairfind(request->reply->vps, 1129, 0);
+       emsk = pairfind(request->reply->vps, 1130, 0);
        if (!msk || !emsk) {
                RDEBUG("No EAP-MSK or EAP-EMSK.  Cannot create WiMAX keys.");
                return RLM_MODULE_NOOP;
        }
 
        /*
+        *      If we delete the MS-MPPE-*-Key attributes, then add in
+        *      the WiMAX-MSK so that the client has a key available.
+        */
+       if (inst->delete_mppe_keys) {
+               pairdelete(&request->reply->vps, 16, VENDORPEC_MICROSOFT);
+               pairdelete(&request->reply->vps, 17, VENDORPEC_MICROSOFT);
+
+               vp = radius_pairmake(request, &request->reply->vps, "WiMAX-MSK", "0x00", T_OP_EQ);
+               if (vp) {
+                       memcpy(vp->vp_octets, msk->vp_octets, msk->length);
+                       vp->length = msk->length;
+               }
+       }
+
+       /*
         *      Initialize usage data.
         */
        memcpy(usage_data, "miprk@wimaxforum.org", 21); /* with trailing \0 */
@@ -138,14 +220,13 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
        /*
         *      MIP-RK-2 = HMAC-SSHA256(EMSK, MIP-RK-1 | usage-data | 0x01)
         */
-       HMAC_CTX_init(&hmac);
        HMAC_Init_ex(&hmac, emsk->vp_octets, emsk->length, EVP_sha256(), NULL);
        
        HMAC_Update(&hmac, (const uint8_t *) &mip_rk_1, rk1_len);
        HMAC_Update(&hmac, &usage_data[0], sizeof(usage_data));
        HMAC_Final(&hmac, &mip_rk_2[0], &rk2_len);
 
-       vp = pairfind(request->reply->vps, PW_SESSION_TIMEOUT);
+       vp = pairfind(request->reply->vps, PW_SESSION_TIMEOUT, 0);
        if (vp) rk_lifetime = vp->vp_integer;
 
        memcpy(mip_rk, mip_rk_1, rk1_len);
@@ -155,7 +236,6 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
        /*
         *      MIP-SPI = HMAC-SSHA256(MIP-RK, "SPI CMIP PMIP");
         */
-       HMAC_CTX_init(&hmac);
        HMAC_Init_ex(&hmac, mip_rk, rk_len, EVP_sha256(), NULL);
        
        HMAC_Update(&hmac, (const uint8_t *) "SPI CMIP PMIP", 12);
@@ -188,8 +268,8 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
        /*
         *      Calculate mobility keys
         */
-       mn_nai = pairfind(request->packet->vps, 1900);
-       if (!mn_nai) mn_nai = pairfind(request->reply->vps, 1900);
+       mn_nai = pairfind(request->packet->vps, 1900, 0);
+       if (!mn_nai) mn_nai = pairfind(request->reply->vps, 1900, 0);
        if (!mn_nai) {
                RDEBUG("WARNING: WiMAX-MN-NAI was not found in the request or in the reply.");
                RDEBUG("WARNING: We cannot calculate MN-HA keys.");
@@ -199,7 +279,7 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
         *      WiMAX-IP-Technology
         */
        vp = NULL;
-       if (mn_nai) vp = pairfind(request->reply->vps, WIMAX2ATTR(23));
+       if (mn_nai) vp = pairfind(request->reply->vps, 23, VENDORPEC_WIMAX);
        if (!vp) {
                RDEBUG("WARNING: WiMAX-IP-Technology not found in reply.");
                RDEBUG("WARNING: Not calculating MN-HA keys");
@@ -210,7 +290,7 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                /*
                 *      Look for WiMAX-hHA-IP-MIP4
                 */
-               ip = pairfind(request->reply->vps, WIMAX2ATTR(6));
+               ip = pairfind(request->reply->vps, 6, VENDORPEC_WIMAX);
                if (!ip) {
                        RDEBUG("WARNING: WiMAX-hHA-IP-MIP4 not found.  Cannot calculate MN-HA-PMIP4 key");
                        break;
@@ -220,7 +300,6 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                 *      MN-HA-PMIP4 =
                 *         H(MIP-RK, "PMIP4 MN HA" | HA-IPv4 | MN-NAI);
                 */
-               HMAC_CTX_init(&hmac);
                HMAC_Init_ex(&hmac, mip_rk, rk_len, EVP_sha1(), NULL);
 
                HMAC_Update(&hmac, (const uint8_t *) "PMIP4 MN HA", 11);
@@ -231,10 +310,10 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                /*
                 *      Put MN-HA-PMIP4 into WiMAX-MN-hHA-MIP4-Key
                 */
-               vp = pairfind(request->reply->vps, WIMAX2ATTR(10));
+               vp = pairfind(request->reply->vps, 10, VENDORPEC_WIMAX);
                if (!vp) {
                        vp = radius_paircreate(request, &request->reply->vps,
-                                              WIMAX2ATTR(10), PW_TYPE_OCTETS);
+                                              10, VENDORPEC_WIMAX, PW_TYPE_OCTETS);
                }
                if (!vp) {
                        RDEBUG("WARNING: Failed creating WiMAX-MN-hHA-MIP4-Key");
@@ -246,10 +325,10 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                /*
                 *      Put MN-HA-PMIP4-SPI into WiMAX-MN-hHA-MIP4-SPI
                 */
-               vp = pairfind(request->reply->vps, WIMAX2ATTR(11));
+               vp = pairfind(request->reply->vps, 11, VENDORPEC_WIMAX);
                if (!vp) {
                        vp = radius_paircreate(request, &request->reply->vps,
-                                              WIMAX2ATTR(11), PW_TYPE_INTEGER);
+                                              11, VENDORPEC_WIMAX, PW_TYPE_INTEGER);
                }
                if (!vp) {
                        RDEBUG("WARNING: Failed creating WiMAX-MN-hHA-MIP4-SPI");
@@ -262,7 +341,7 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                /*
                 *      Look for WiMAX-hHA-IP-MIP4
                 */
-               ip = pairfind(request->reply->vps, WIMAX2ATTR(6));
+               ip = pairfind(request->reply->vps, 6, VENDORPEC_WIMAX);
                if (!ip) {
                        RDEBUG("WARNING: WiMAX-hHA-IP-MIP4 not found.  Cannot calculate MN-HA-CMIP4 key");
                        break;
@@ -272,7 +351,6 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                 *      MN-HA-CMIP4 =
                 *         H(MIP-RK, "CMIP4 MN HA" | HA-IPv4 | MN-NAI);
                 */
-               HMAC_CTX_init(&hmac);
                HMAC_Init_ex(&hmac, mip_rk, rk_len, EVP_sha1(), NULL);
 
                HMAC_Update(&hmac, (const uint8_t *) "CMIP4 MN HA", 11);
@@ -283,10 +361,10 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                /*
                 *      Put MN-HA-CMIP4 into WiMAX-MN-hHA-MIP4-Key
                 */
-               vp = pairfind(request->reply->vps, WIMAX2ATTR(10));
+               vp = pairfind(request->reply->vps, 10, VENDORPEC_WIMAX);
                if (!vp) {
                        vp = radius_paircreate(request, &request->reply->vps,
-                                              WIMAX2ATTR(10), PW_TYPE_OCTETS);
+                                              10, VENDORPEC_WIMAX, PW_TYPE_OCTETS);
                }
                if (!vp) {
                        RDEBUG("WARNING: Failed creating WiMAX-MN-hHA-MIP4-Key");
@@ -298,10 +376,10 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                /*
                 *      Put MN-HA-CMIP4-SPI into WiMAX-MN-hHA-MIP4-SPI
                 */
-               vp = pairfind(request->reply->vps, WIMAX2ATTR(11));
+               vp = pairfind(request->reply->vps, 11, VENDORPEC_WIMAX);
                if (!vp) {
                        vp = radius_paircreate(request, &request->reply->vps,
-                                              WIMAX2ATTR(11), PW_TYPE_INTEGER);
+                                              11, VENDORPEC_WIMAX, PW_TYPE_INTEGER);
                }
                if (!vp) {
                        RDEBUG("WARNING: Failed creating WiMAX-MN-hHA-MIP4-SPI");
@@ -314,7 +392,7 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                /*
                 *      Look for WiMAX-hHA-IP-MIP6
                 */
-               ip = pairfind(request->reply->vps, WIMAX2ATTR(7));
+               ip = pairfind(request->reply->vps, 7, VENDORPEC_WIMAX);
                if (!ip) {
                        RDEBUG("WARNING: WiMAX-hHA-IP-MIP6 not found.  Cannot calculate MN-HA-CMIP6 key");
                        break;
@@ -324,7 +402,6 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                 *      MN-HA-CMIP6 =
                 *         H(MIP-RK, "CMIP6 MN HA" | HA-IPv6 | MN-NAI);
                 */
-               HMAC_CTX_init(&hmac);
                HMAC_Init_ex(&hmac, mip_rk, rk_len, EVP_sha1(), NULL);
 
                HMAC_Update(&hmac, (const uint8_t *) "CMIP6 MN HA", 11);
@@ -335,10 +412,10 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                /*
                 *      Put MN-HA-CMIP6 into WiMAX-MN-hHA-MIP6-Key
                 */
-               vp = pairfind(request->reply->vps, WIMAX2ATTR(12));
+               vp = pairfind(request->reply->vps, 12, VENDORPEC_WIMAX);
                if (!vp) {
                        vp = radius_paircreate(request, &request->reply->vps,
-                                              WIMAX2ATTR(12), PW_TYPE_OCTETS);
+                                              12, VENDORPEC_WIMAX, PW_TYPE_OCTETS);
                }
                if (!vp) {
                        RDEBUG("WARNING: Failed creating WiMAX-MN-hHA-MIP6-Key");
@@ -350,10 +427,10 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                /*
                 *      Put MN-HA-CMIP6-SPI into WiMAX-MN-hHA-MIP6-SPI
                 */
-               vp = pairfind(request->reply->vps, WIMAX2ATTR(13));
+               vp = pairfind(request->reply->vps, 13, VENDORPEC_WIMAX);
                if (!vp) {
                        vp = radius_paircreate(request, &request->reply->vps,
-                                              WIMAX2ATTR(13), PW_TYPE_INTEGER);
+                                              13, VENDORPEC_WIMAX, PW_TYPE_INTEGER);
                }
                if (!vp) {
                        RDEBUG("WARNING: Failed creating WiMAX-MN-hHA-MIP6-SPI");
@@ -371,9 +448,8 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
         *
         *      FA-RK= H(MIP-RK, "FA-RK")
         */
-       fa_rk = pairfind(request->reply->vps, WIMAX2ATTR(14));
-       if (fa_rk && (fa_rk->length == 0)) {
-               HMAC_CTX_init(&hmac);
+       fa_rk = pairfind(request->reply->vps, 14, VENDORPEC_WIMAX);
+       if (fa_rk && (fa_rk->length <= 1)) {
                HMAC_Init_ex(&hmac, mip_rk, rk_len, EVP_sha1(), NULL);
                
                HMAC_Update(&hmac, (const uint8_t *) "FA-RK", 5);
@@ -389,10 +465,10 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
         *      really MIP-SPI.  Clear?  Of course.  This is WiMAX.
         */
        if (fa_rk) {
-               vp = pairfind(request->reply->vps, WIMAX2ATTR(61));
+               vp = pairfind(request->reply->vps, 61, VENDORPEC_WIMAX);
                if (!vp) {
                        vp = radius_paircreate(request, &request->reply->vps,
-                                              WIMAX2ATTR(61), PW_TYPE_INTEGER);
+                                              61, VENDORPEC_WIMAX, PW_TYPE_INTEGER);
                }
                if (!vp) {
                        RDEBUG("WARNING: Failed creating WiMAX-FA-RK-SPI");
@@ -404,9 +480,8 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
        /*
         *      Generate MN-FA = H(FA-RK, "MN FA" | FA-IP | MN-NAI)
         */
-       ip = pairfind(request->reply->vps, 1901);
+       ip = pairfind(request->reply->vps, 1901, 0);
        if (fa_rk && ip && mn_nai) {
-               HMAC_CTX_init(&hmac);
                HMAC_Init_ex(&hmac, fa_rk->vp_octets, fa_rk->length,
                             EVP_sha1(), NULL);
                
@@ -417,7 +492,7 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                HMAC_Final(&hmac, &mip_rk_1[0], &rk1_len);
 
                vp = radius_paircreate(request, &request->reply->vps,
-                                      1902, PW_TYPE_OCTETS);
+                                      1902, 0, PW_TYPE_OCTETS);
                if (!vp) {
                        RDEBUG("WARNING: Failed creating WiMAX-MN-FA");
                } else {
@@ -431,7 +506,7 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
         *
         *      WiMAX-RRQ-MN-HA-SPI
         */
-       vp = pairfind(request->packet->vps, WIMAX2ATTR(20));
+       vp = pairfind(request->packet->vps, 20, VENDORPEC_WIMAX);
        if (vp) {
                RDEBUG("Client requested MN-HA key: Should use SPI to look up key from storage.");
                if (!mn_nai) {
@@ -441,7 +516,7 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                /*
                 *      WiMAX-RRQ-HA-IP
                 */
-               if (!pairfind(request->packet->vps, WIMAX2ATTR(18))) {
+               if (!pairfind(request->packet->vps, 18, VENDORPEC_WIMAX)) {
                        RDEBUG("WARNING: HA-IP was not found!");
                }
 
@@ -449,7 +524,7 @@ static int wimax_postauth(UNUSED void *instance, REQUEST *request)
                /*
                 *      WiMAX-HA-RK-Key-Requested
                 */
-               vp = pairfind(request->packet->vps, WIMAX2ATTR(58));
+               vp = pairfind(request->packet->vps, 58, VENDORPEC_WIMAX);
                if (vp && (vp->vp_integer == 1)) {
                        RDEBUG("Client requested HA-RK: Should use IP to look it up from storage.");
                }
@@ -477,8 +552,8 @@ module_t rlm_wimax = {
        RLM_MODULE_INIT,
        "wimax",
        RLM_TYPE_THREAD_SAFE,           /* type */
-       NULL,                           /* instantiation */
-       NULL,                           /* detach */
+       wimax_instantiate,              /* instantiation */
+       wimax_detach,                   /* detach */
        {
                NULL,                   /* authentication */
                wimax_authorize,        /* authorization */