]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
fixes #108 Add function to convert FR value pair types to network byte order
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 17 Oct 2012 14:32:41 +0000 (15:32 +0100)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 17 Oct 2012 15:52:44 +0000 (16:52 +0100)
src/include/base64.h
src/include/libradius.h
src/lib/base64.c
src/lib/radius.c
src/main/xlat.c

index 84ecf52e98f1d9d709c8118e7c3d6069f94f2bda..645e111906f0ed2a2c6bc2aae04a2cead5b4c48a 100644 (file)
@@ -31,10 +31,10 @@ RCSIDH(base64_h, "$Id$")
 
 extern int fr_isbase64 (char ch);
 
-extern void fr_base64_encode (const char *in, size_t inlen,
+extern void fr_base64_encode (const uint8_t *in, size_t inlen,
                              char *out, size_t outlen);
 
-extern size_t fr_base64_encode_alloc (const char *in, size_t inlen, char **out);
+extern size_t fr_base64_encode_alloc (const uint8_t *in, size_t inlen, char **out);
 
 extern int fr_base64_decode (const char *in, size_t inlen,
                             char *out, size_t *outlen);
index 7f757770bd891af0ac5a6f360d8a4bac00ad8d37..1c15f32e7cbe42e91e63f776267b31a132c4a44f 100644 (file)
@@ -344,6 +344,7 @@ int         rad_chap_encode(RADIUS_PACKET *packet, uint8_t *output,
 VALUE_PAIR     *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET *original,
                             const char *secret, int attribute, int length,
                             const uint8_t *data);
+ssize_t                rad_vp2data(const VALUE_PAIR *vp, uint8_t *out, size_t outlen);
 int            rad_vp2attr(const RADIUS_PACKET *packet,
                            const RADIUS_PACKET *original, const char *secret,
                            const VALUE_PAIR *vp, uint8_t *ptr);
index 2541bf1c05da061a1da0aeb094417687a15eb87f..b796c6ad480b0b3e189d732a2a1b804b5cda4ab7 100644 (file)
@@ -63,7 +63,7 @@ to_uchar (char ch)
    If OUTLEN is less than FR_BASE64_ENC_LENGTH(INLEN), write as many bytes as
    possible.  If OUTLEN is larger than FR_BASE64_ENC_LENGTH(INLEN), also zero
    terminate the output buffer. */
-void fr_base64_encode (const char *in, size_t inlen,
+void fr_base64_encode (const uint8_t *in, size_t inlen,
                       char *out, size_t outlen)
 {
   static const char b64str[64] =
@@ -71,23 +71,23 @@ void fr_base64_encode (const char *in, size_t inlen,
 
   while (inlen && outlen)
     {
-      *out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
+      *out++ = b64str[(in[0] >> 2) & 0x3f];
       if (!--outlen)
        break;
-      *out++ = b64str[((to_uchar (in[0]) << 4)
-                      + (--inlen ? to_uchar (in[1]) >> 4 : 0))
+      *out++ = b64str[((in[0] << 4)
+                      + (--inlen ? in[1] >> 4 : 0))
                      & 0x3f];
       if (!--outlen)
        break;
       *out++ =
        (inlen
-        ? b64str[((to_uchar (in[1]) << 2)
-                  + (--inlen ? to_uchar (in[2]) >> 6 : 0))
+        ? b64str[((in[1] << 2)
+                  + (--inlen ? in[2] >> 6 : 0))
                  & 0x3f]
         : '=');
       if (!--outlen)
        break;
-      *out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
+      *out++ = inlen ? b64str[in[2] & 0x3f] : '=';
       if (!--outlen)
        break;
       if (inlen)
@@ -110,7 +110,7 @@ void fr_base64_encode (const char *in, size_t inlen,
    indicates length of the requested memory block, i.e.,
    FR_BASE64_ENC_LENGTH(inlen) + 1. */
 size_t
-fr_base64_encode_alloc (const char *in, size_t inlen, char **out)
+fr_base64_encode_alloc (const uint8_t *in, size_t inlen, char **out)
 {
   size_t outlen = 1 + FR_BASE64_ENC_LENGTH (inlen);
 
index 7c5a4372db0cd0c56e77fe27264bc8b9bf7c8ad1..397281721c501ecf9794c8f640a867df3c77962e 100644 (file)
@@ -2740,6 +2740,69 @@ VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET *origin
        return data2vp(packet, original, secret, attribute, length, data, vp);
 }
 
+/**
+ *     Converts vp_data to network byte order
+ *     Returns:
+ *             -1 on error, or the length of the value
+ */
+ssize_t rad_vp2data(const VALUE_PAIR *vp, uint8_t *out, size_t outlen)
+{
+       size_t          len = 0;
+       uint32_t        lvalue;
+
+       len = vp->length;
+       if (outlen < len) {
+               fr_strerror_printf("ERROR: rad_vp2data buffer passed too small");
+               return -1;
+       }
+       
+       switch(vp->type) {
+               case PW_TYPE_STRING:
+               case PW_TYPE_OCTETS:
+               case PW_TYPE_IFID:
+               case PW_TYPE_IPADDR:
+               case PW_TYPE_IPV6ADDR:
+               case PW_TYPE_IPV6PREFIX:
+               case PW_TYPE_ABINARY:
+               case PW_TYPE_TLV:
+                       memcpy(out, vp->vp_octets, len);
+                       break;
+               case PW_TYPE_BYTE:
+                       out[0] = vp->vp_integer & 0xff;
+                       break;
+       
+               case PW_TYPE_SHORT:
+                       out[0] = (vp->vp_integer >> 8) & 0xff;
+                       out[1] = vp->vp_integer & 0xff;
+                       break;
+       
+               case PW_TYPE_INTEGER:
+                       lvalue = htonl(vp->vp_integer);
+                       memcpy(out, &lvalue, sizeof(lvalue));
+                       break;
+
+               case PW_TYPE_DATE:
+                       lvalue = htonl(vp->vp_date);
+                       memcpy(out, &lvalue, sizeof(lvalue));
+                       break;
+       
+               case PW_TYPE_SIGNED:
+               {
+                       int32_t slvalue;
+                       
+                       slvalue = htonl(vp->vp_signed);
+                       memcpy(out, &slvalue, sizeof(slvalue));
+                       break;
+               }
+               /* unknown type: ignore it */
+               default:                
+                       fr_strerror_printf("ERROR: Unknown attribute type %d",
+                                          vp->type);
+                       return -1;
+       }
+       
+       return len;
+}
 
 /*
  *     Calculate/check digest, and decode radius attributes.
index 42c4fdffd611a048d6039941fba773ff82a321c6..dddc64cea81457932612abb1a0df05ea4471f24a 100644 (file)
@@ -542,8 +542,10 @@ static size_t xlat_hex(UNUSED void *instance, REQUEST *request,
                       UNUSED RADIUS_ESCAPE_STRING func)
 {
        size_t i;
-       uint8_t *p;
        VALUE_PAIR *vp;
+       uint8_t buffer[MAX_STRING_LEN];
+       ssize_t ret;
+       size_t  len;
 
        while (isspace((int) *fmt)) fmt++;
 
@@ -551,21 +553,23 @@ static size_t xlat_hex(UNUSED void *instance, REQUEST *request,
                *out = '\0';
                return 0;
        }
-
+       
+       ret = rad_vp2data(vp, buffer, sizeof(buffer));
+       len = (size_t) ret;
+       
        /*
         *      Don't truncate the data.
         */
-       if (outlen < (vp->length * 2)) {
+       if ((ret < 0 ) || (outlen < (len * 2))) {
                *out = 0;
                return 0;
        }
 
-       p = &vp->vp_octets[0];
-       for (i = 0; i < vp->length; i++) {
-               snprintf(out + 2*i, 3, "%02x", p[i]);
+       for (i = 0; i < len; i++) {
+               snprintf(out + 2*i, 3, "%02x", buffer[i]);
        }
 
-       return vp->length * 2;
+       return len * 2;
 }
 
 /**
@@ -575,7 +579,10 @@ static size_t xlat_base64(UNUSED void *instance, REQUEST *request,
                          const char *fmt, char *out, size_t outlen)
 {
        VALUE_PAIR *vp;
-       size_t len;
+       uint8_t buffer[MAX_STRING_LEN];
+       ssize_t ret;
+       size_t  len;
+       size_t  enc;
        
        while (isspace((int) *fmt)) fmt++;
 
@@ -584,19 +591,27 @@ static size_t xlat_base64(UNUSED void *instance, REQUEST *request,
                return 0;
        }
        
-       len = FR_BASE64_ENC_LENGTH(vp->length);
+       ret = rad_vp2data(vp, buffer, sizeof(buffer));
+       if (ret < 0) {
+               *out = 0;
+               return 0;
+       }
+       
+       len = (size_t) ret;
+       
+       enc = FR_BASE64_ENC_LENGTH(len);
        
        /*
         *      Don't truncate the data.
         */
-       if (outlen < (len + 1)) {
+       if (outlen < (enc + 1)) {
                *out = 0;
                return 0;
        }
        
-       fr_base64_encode((char *) vp->vp_octets, vp->length, out, outlen);
+       fr_base64_encode(buffer, len, out, outlen);
 
-       return len;
+       return enc;
 }
 
 #ifdef HAVE_REGEX_H