Back to index

openldap  2.4.31
Functions | Variables
base64.c File Reference
#include "portable.h"
#include <ac/assert.h>
#include <ac/stdlib.h>
#include <ac/ctype.h>
#include <ac/string.h>
#include <ac/socket.h>
#include "lutil.h"

Go to the source code of this file.

Functions

int lutil_b64_ntop (u_char const *src, size_t srclength, char *target, size_t targsize)
int lutil_b64_pton (char const *src, u_char *target, size_t targsize)

Variables

static const char Base64 [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
static const char Pad64 = '='

Function Documentation

int lutil_b64_ntop ( u_char const src,
size_t  srclength,
char *  target,
size_t  targsize 
)

Definition at line 118 of file base64.c.

{
       size_t datalength = 0;
       u_char input[3];
       u_char output[4];
       size_t i;

       while (2 < srclength) {
              input[0] = *src++;
              input[1] = *src++;
              input[2] = *src++;
              srclength -= 3;

              output[0] = input[0] >> 2;
              output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
              output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
              output[3] = input[2] & 0x3f;
              assert(output[0] < 64);
              assert(output[1] < 64);
              assert(output[2] < 64);
              assert(output[3] < 64);

              if (datalength + 4 > targsize)
                     return (-1);
              target[datalength++] = Base64[output[0]];
              target[datalength++] = Base64[output[1]];
              target[datalength++] = Base64[output[2]];
              target[datalength++] = Base64[output[3]];
       }
    
       /* Now we worry about padding. */
       if (0 != srclength) {
              /* Get what's left. */
              input[0] = input[1] = input[2] = '\0';
              for (i = 0; i < srclength; i++)
                     input[i] = *src++;
       
              output[0] = input[0] >> 2;
              output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
              output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
              assert(output[0] < 64);
              assert(output[1] < 64);
              assert(output[2] < 64);

              if (datalength + 4 > targsize)
                     return (-1);
              target[datalength++] = Base64[output[0]];
              target[datalength++] = Base64[output[1]];
              if (srclength == 1)
                     target[datalength++] = Pad64;
              else
                     target[datalength++] = Base64[output[2]];
              target[datalength++] = Pad64;
       }
       if (datalength >= targsize)
              return (-1);
       target[datalength] = '\0';  /* Returned value doesn't count \0. */
       return (datalength);
}

Here is the caller graph for this function:

int lutil_b64_pton ( char const src,
u_char *  target,
size_t  targsize 
)

Definition at line 189 of file base64.c.

{
       int tarindex, state, ch;
       char *pos;

       state = 0;
       tarindex = 0;

       while ((ch = *src++) != '\0') {
              if (isascii(ch) && isspace(ch))    /* Skip whitespace anywhere. */
                     continue;

              if (ch == Pad64)
                     break;

              pos = strchr(Base64, ch);
              if (pos == 0)               /* A non-base64 character. */
                     return (-1);

              switch (state) {
              case 0:
                     if (target) {
                            if ((size_t)tarindex >= targsize)
                                   return (-1);
                            target[tarindex] = (pos - Base64) << 2;
                     }
                     state = 1;
                     break;
              case 1:
                     if (target) {
                            if ((size_t)tarindex + 1 >= targsize)
                                   return (-1);
                            target[tarindex]   |=  (pos - Base64) >> 4;
                            target[tarindex+1]  = ((pos - Base64) & 0x0f)
                                                 << 4 ;
                     }
                     tarindex++;
                     state = 2;
                     break;
              case 2:
                     if (target) {
                            if ((size_t)tarindex + 1 >= targsize)
                                   return (-1);
                            target[tarindex]   |=  (pos - Base64) >> 2;
                            target[tarindex+1]  = ((pos - Base64) & 0x03)
                                                 << 6;
                     }
                     tarindex++;
                     state = 3;
                     break;
              case 3:
                     if (target) {
                            if ((size_t)tarindex >= targsize)
                                   return (-1);
                            target[tarindex] |= (pos - Base64);
                     }
                     tarindex++;
                     state = 0;
                     break;
              default:
                     abort();
              }
       }

       /*
        * We are done decoding Base-64 chars.  Let's see if we ended
        * on a byte boundary, and/or with erroneous trailing characters.
        */

       if (ch == Pad64) {          /* We got a pad char. */
              ch = *src++;         /* Skip it, get next. */
              switch (state) {
              case 0:              /* Invalid = in first position */
              case 1:              /* Invalid = in second position */
                     return (-1);

              case 2:              /* Valid, means one byte of info */
                     /* Skip any number of spaces. */
                     for ((void)NULL; ch != '\0'; ch = *src++)
                            if (! (isascii(ch) && isspace(ch)))
                                   break;
                     /* Make sure there is another trailing = sign. */
                     if (ch != Pad64)
                            return (-1);
                     ch = *src++;         /* Skip the = */
                     /* Fall through to "single trailing =" case. */
                     /* FALLTHROUGH */

              case 3:              /* Valid, means two bytes of info */
                     /*
                      * We know this char is an =.  Is there anything but
                      * whitespace after it?
                      */
                     for ((void)NULL; ch != '\0'; ch = *src++)
                            if (! (isascii(ch) && isspace(ch)))
                                   return (-1);

                     /*
                      * Now make sure for cases 2 and 3 that the "extra"
                      * bits that slopped past the last full byte were
                      * zeros.  If we don't check them, they become a
                      * subliminal channel.
                      */
                     if (target && target[tarindex] != 0)
                            return (-1);
              }
       } else {
              /*
               * We ended by seeing the end of the string.  Make sure we
               * have no partial bytes lying around.
               */
              if (state != 0)
                     return (-1);
       }

       return (tarindex);
}

Here is the caller graph for this function:


Variable Documentation

const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" [static]

Definition at line 50 of file base64.c.

const char Pad64 = '=' [static]

Definition at line 52 of file base64.c.