Manual merge of aec08bce7f
authorAlan T. DeKok <aland@freeradius.org>
Mon, 2 Aug 2010 13:54:46 +0000 (15:54 +0200)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 2 Aug 2010 13:54:46 +0000 (15:54 +0200)
Better handle a "known" attribute with invalid length

If we receive an "integer" attribute with length "10", don't
leave the name as "Foo-Bar".  Instead, make it clear that the
attribute is unknown, and print it as "Attr-%d"

src/include/libradius.h
src/lib/radius.c
src/lib/valuepair.c

index c8f7ce9..1d12fd7 100644 (file)
@@ -331,6 +331,7 @@ int         rad_vp2attr(const RADIUS_PACKET *packet,
 
 /* valuepair.c */
 VALUE_PAIR     *pairalloc(DICT_ATTR *da);
+VALUE_PAIR     *paircreate_raw(int attr, int vendor, int type, VALUE_PAIR *);
 VALUE_PAIR     *paircreate(int attr, int vendor, int type);
 void           pairfree(VALUE_PAIR **);
 void            pairbasicfree(VALUE_PAIR *pair);
index 84e88ef..112e35d 100644 (file)
@@ -2437,16 +2437,35 @@ static VALUE_PAIR *data2vp(const RADIUS_PACKET *packet,
 
        default:
        raw:
-               vp->type = PW_TYPE_OCTETS;
-               vp->length = length;
-               memcpy(vp->vp_octets, data, length);
-
-
                /*
-                *      Ensure there's no encryption or tag stuff,
-                *      we just pass the attribute as-is.
+                *      Change the name to show the user that the
+                *      attribute is not of the correct format.
                 */
-               memset(&vp->flags, 0, sizeof(vp->flags));
+               {
+                       int attr = vp->attribute;
+                       int vendor = vp->vendor;
+                       VALUE_PAIR *vp2;
+
+                       vp2 = pairalloc(NULL);
+                       if (!vp2) {
+                               pairfree(&vp);
+                               return NULL;
+                       }
+                       pairfree(&vp);
+                       vp = vp2;
+
+                       /*
+                        *      This sets "vp->flags" appropriately,
+                        *      and vp->type.
+                        */
+                       if (!paircreate_raw(attr, vendor, PW_TYPE_OCTETS, vp)) {
+                               return NULL;
+                       }
+
+                       vp->length = length;
+                       memcpy(vp->vp_octets, data, length);
+               }
+               break;
        }
 
        return vp;
index efe37db..a85ecc4 100644 (file)
@@ -134,6 +134,34 @@ VALUE_PAIR *pairalloc(DICT_ATTR *da)
        return vp;
 }
 
+/*
+ *     Create a new valuepair.
+ */
+VALUE_PAIR *paircreate_raw(int attr, int vendor, int type, VALUE_PAIR *vp)
+{
+       char *p = (char *) (vp + 1);
+
+       if (!vp->flags.unknown_attr) {
+               pairfree(&vp);
+               return NULL;
+       }
+
+       vp->vendor = vendor;
+       vp->attribute = attr;
+       vp->operator = T_OP_EQ;
+       vp->name = p;
+       vp->type = type;
+       vp->length = 0;
+       memset(&vp->flags, 0, sizeof(vp->flags));
+       vp->flags.unknown_attr = 1;
+       
+       if (!vp_print_name(p, FR_VP_NAME_LEN, vp->attribute, vp->vendor)) {
+               free(vp);
+               return NULL;
+       }
+
+       return vp;
+}
 
 /*
  *     Create a new valuepair.
@@ -153,19 +181,7 @@ VALUE_PAIR *paircreate(int attr, int vendor, int type)
        /*
         *      It isn't in the dictionary: update the name.
         */
-       if (!da) {
-               char *p = (char *) (vp + 1);
-               
-               vp->vendor = vendor;
-               vp->attribute = attr;
-               vp->name = p;
-               vp->type = type; /* be forgiving */
-
-               if (!vp_print_name(p, FR_VP_NAME_LEN, attr, vendor)) {
-                       free(vp);
-                       return NULL;
-               }
-       }
+       if (!da) return paircreate_raw(attr, vendor, type, vp);
 
        return vp;
 }
@@ -326,6 +342,13 @@ VALUE_PAIR *paircopyvp(const VALUE_PAIR *vp)
                return NULL;
        }
        memcpy(n, vp, sizeof(*n) + name_len);
+
+       /*
+        *      Reset the name field to point to the NEW attribute,
+        *      rather than to the OLD one.
+        */
+       if (vp->flags.unknown_attr) n->name = (char *) (n + 1);
+
        n->next = NULL;
 
        if ((n->type == PW_TYPE_TLV) &&