Problem with expansion of %{Ldap-UserDn} containing UTF-8 (cf. Bug #411)

Enrik Berkhan enrik#freeradius at planb.de
Mon Aug 27 17:05:55 CEST 2007


Alan DeKok wrote:

>   Bleah.  There's no need to use a function with local non-thread-aware
> storage.  It's easy to know what a valid UTF-8 character is.  We should
> just check ourselves, and escape anything that isn't valid.

You're right. So this could be a start:



static int valid_utf8(const unsigned char *p, size_t len)
{
   if (len >= 1
       && p[0] < 0x7f) {
     return 1;
   } else if (len >= 2
              && p[0] >= 0xC0 && p[0] < 0xE0
              && (p[1]&0x80) == 0x80) {
     return 2;
   } else if (len >= 3
              && p[0] >= 0xE0 && p[0] < 0xF0
              && (p[1]&0x80) == 0x80 && (p[2]&0x80) == 0x80) {
     return 3;
   } else if (len >= 4
              && p[0] >= 0xF0 && p[0] < 0xF8
              && (p[1]&0x80) == 0x80 && (p[2]&0x80) == 0x80
              && (p[3]&0x80) == 0x80) {
     return 4;
   } else if (len >= 5
              && p[0] >= 0xF8 && p[0] < 0xFC
              && (p[1]&0x80) == 0x80 && (p[2]&0x80) == 0x80
              && (p[3]&0x80) == 0x80 && (p[4]&0x80) == 0x80) {
     return 5;
   } else if (len >= 6
              && p[0] >= 0xFC && p[0] < 0xFE
              && (p[1]&0x80) == 0x80 && (p[2]&0x80) == 0x80
              && (p[3]&0x80) == 0x80 && (p[4]&0x80) == 0x80
              && (p[5]&0x80) == 0x80) {
     return 6;
   }
   return 0;
}

/*
  *      Check if string contains valid UTF-8, escape violating bytes.
  *      The output string has to be _at least_ 4x the size
  *      of the input string!
  */
void librad_utf8_sanitize(const char *in, size_t inlen,
                           char *out, size_t outlen)
{
   while (inlen && outlen) {
     size_t next = valid_utf8(in, inlen);
     if (next) {
       if (outlen > next) {
         inlen -= next;
         outlen -= next;
         while(next--)
           *out++ = *in++;
       } else {
         goto no_more;
       }
     } else {
       if (outlen > 4) { /* room for \ooo\0 */
         sprintf(out, "\\%03o", (unsigned char)(*in++)&0xff);
         out += 4;
         inlen--;
         outlen -= 4;
       } else {
         goto no_more;
       }
     }
   }

no_more:
   *out = 0;
}


Enrik




More information about the Freeradius-Devel mailing list