Back to index

openldap  2.4.31
Classes | Defines | Typedefs | Functions | Variables
encode.c File Reference
#include "portable.h"
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <ac/stdlib.h>
#include <ac/stdarg.h>
#include <ac/socket.h>
#include <ac/string.h>
#include "lber-int.h"

Go to the source code of this file.

Classes

struct  seqorset_header
union  seqorset_header.next_sos

Defines

#define OCTET_SIZE(type)   ((ber_len_t) (sizeof(type)*CHAR_BIT + 7) / 8)
#define TAGBUF_SIZE   OCTET_SIZE(ber_tag_t)
#define LENBUF_SIZE   (1 + OCTET_SIZE(ber_len_t))
#define HEADER_SIZE   (TAGBUF_SIZE + LENBUF_SIZE)
#define MAXINT_BERSIZE   (INT_MAX>0xffffffffUL ? (ber_len_t) 0xffffffffUL : INT_MAX-HEADER_SIZE)
#define MAXINT_BERSIZE_OCTETS   4
#define SOS_LENLEN
#define SOS_TAG_END(header)   ((unsigned char *) &(header).next_sos - 1)

Typedefs

typedef ber_uint_t ber_elem_size_t
typedef struct seqorset_header Seqorset_header

Functions

static unsigned char * ber_prepend_tag (unsigned char *ptr, ber_tag_t tag)
static unsigned char * ber_prepend_len (unsigned char *ptr, ber_len_t len)
int ber_encode_oid (BerValue *in, BerValue *out)
static int ber_put_int_or_enum (BerElement *ber, ber_int_t num, ber_tag_t tag)
int ber_put_enum (BerElement *ber, ber_int_t num, ber_tag_t tag)
int ber_put_int (BerElement *ber, ber_int_t num, ber_tag_t tag)
int ber_put_ostring (BerElement *ber, LDAP_CONST char *str, ber_len_t len, ber_tag_t tag)
int ber_put_berval (BerElement *ber, struct berval *bv, ber_tag_t tag)
int ber_put_string (BerElement *ber, LDAP_CONST char *str, ber_tag_t tag)
int ber_put_bitstring (BerElement *ber, LDAP_CONST char *str, ber_len_t blen, ber_tag_t tag)
int ber_put_null (BerElement *ber, ber_tag_t tag)
int ber_put_boolean (BerElement *ber, ber_int_t boolval, ber_tag_t tag)
static int ber_start_seqorset (BerElement *ber, ber_tag_t tag)
int ber_start_seq (BerElement *ber, ber_tag_t tag)
int ber_start_set (BerElement *ber, ber_tag_t tag)
static int ber_put_seqorset (BerElement *ber)
int ber_put_seq (BerElement *ber)
int ber_put_set (BerElement *ber)
int ber_printf (BerElement *ber, LDAP_CONST char *fmt,...)

Variables

static ber_tag_t lber_int_null = 0

Class Documentation

struct seqorset_header

Definition at line 349 of file encode.c.

Class Members
union seqorset_header next_sos
char xtagbuf
union seqorset_header.next_sos

Definition at line 351 of file encode.c.

Class Members
ber_elem_size_t offset
char padding

Define Documentation

Definition at line 49 of file encode.c.

#define LENBUF_SIZE   (1 + OCTET_SIZE(ber_len_t))

Definition at line 48 of file encode.c.

#define MAXINT_BERSIZE   (INT_MAX>0xffffffffUL ? (ber_len_t) 0xffffffffUL : INT_MAX-HEADER_SIZE)

Definition at line 68 of file encode.c.

#define MAXINT_BERSIZE_OCTETS   4

Definition at line 70 of file encode.c.

#define OCTET_SIZE (   type)    ((ber_len_t) (sizeof(type)*CHAR_BIT + 7) / 8)

Definition at line 46 of file encode.c.

#define SOS_LENLEN
Value:

Definition at line 345 of file encode.c.

#define SOS_TAG_END (   header)    ((unsigned char *) &(header).next_sos - 1)

Definition at line 355 of file encode.c.

#define TAGBUF_SIZE   OCTET_SIZE(ber_tag_t)

Definition at line 47 of file encode.c.


Typedef Documentation

typedef ber_uint_t ber_elem_size_t

Definition at line 71 of file encode.c.


Function Documentation

int ber_encode_oid ( BerValue in,
BerValue out 
)

Definition at line 112 of file encode.c.

{
       unsigned char *der;
       unsigned long val1, val;
       int i, j, len;
       char *ptr, *end, *inend;

       assert( in != NULL );
       assert( out != NULL );

       if ( !out->bv_val || out->bv_len < in->bv_len/2 )
              return -1;

       der = (unsigned char *) out->bv_val;
       ptr = in->bv_val;
       inend = ptr + in->bv_len;

       /* OIDs start with <0-1>.<0-39> or 2.<any>, DER-encoded 40*val1+val2 */
       if ( !isdigit( (unsigned char) *ptr )) return -1;
       val1 = strtoul( ptr, &end, 10 );
       if ( end == ptr || val1 > 2 ) return -1;
       if ( *end++ != '.' || !isdigit( (unsigned char) *end )) return -1;
       val = strtoul( end, &ptr, 10 );
       if ( ptr == end ) return -1;
       if ( val > (val1 < 2 ? 39 : LBER_OID_COMPONENT_MAX - 80) ) return -1;
       val += val1 * 40;

       for (;;) {
              if ( ptr > inend ) return -1;

              /* Write the OID component little-endian, then reverse it */
              len = 0;
              do {
                     der[len++] = (val & 0xff) | 0x80;
              } while ( (val >>= 7) != 0 );
              der[0] &= 0x7f;
              for ( i = 0, j = len; i < --j; i++ ) {
                     unsigned char tmp = der[i];
                     der[i] = der[j];
                     der[j] = tmp;
              }
              der += len;

              if ( ptr == inend )
                     break;

              if ( *ptr++ != '.' ) return -1;
              if ( !isdigit( (unsigned char) *ptr )) return -1;
              val = strtoul( ptr, &end, 10 );
              if ( end == ptr || val > LBER_OID_COMPONENT_MAX ) return -1;
              ptr = end;
       }

       out->bv_len = (char *)der - out->bv_val;
       return 0;
}

Here is the call graph for this function:

static unsigned char* ber_prepend_len ( unsigned char *  ptr,
ber_len_t  len 
) [static]

Definition at line 87 of file encode.c.

{
       /*
        * short len if it's less than 128 - one byte giving the len,
        * with bit 8 0.
        * long len otherwise - one byte with bit 8 set, giving the
        * length of the length, followed by the length itself.
        */

       *--ptr = (unsigned char) len & 0xffU;

       if ( len >= 0x80 ) {
              unsigned char *endptr = ptr--;

              while ( (len >>= 8) != 0 ) {
                     *ptr-- = (unsigned char) len & 0xffU;
              }
              *ptr = (unsigned char) (endptr - ptr) + 0x80U;
       }

       return ptr;
}

Here is the caller graph for this function:

static unsigned char* ber_prepend_tag ( unsigned char *  ptr,
ber_tag_t  tag 
) [static]

Definition at line 76 of file encode.c.

{
       do {
              *--ptr = (unsigned char) tag & 0xffU;
       } while ( (tag >>= 8) != 0 );

       return ptr;
}

Here is the caller graph for this function:

int ber_printf ( BerElement *  ber,
LDAP_CONST char *  fmt,
  ... 
)

Definition at line 502 of file encode.c.

{
       va_list              ap;
       char          *s, **ss;
       struct berval *bv, **bvp;
       int           rc;
       ber_int_t     i;
       ber_len_t     len;

       assert( ber != NULL );
       assert( fmt != NULL );
       assert( LBER_VALID( ber ) );

       va_start( ap, fmt );

       for ( rc = 0; *fmt && rc != -1; fmt++ ) {
              switch ( *fmt ) {
              case '!': { /* hook */
                            BEREncodeCallback *f;
                            void *p;

                            ber->ber_usertag = 0;

                            f = va_arg( ap, BEREncodeCallback * );
                            p = va_arg( ap, void * );
                            rc = (*f)( ber, p );

                            if ( ber->ber_usertag ) {
                                   goto next;
                            }
                     } break;

              case 'b':     /* boolean */
                     i = va_arg( ap, ber_int_t );
                     rc = ber_put_boolean( ber, i, ber->ber_tag );
                     break;

              case 'i':     /* int */
                     i = va_arg( ap, ber_int_t );
                     rc = ber_put_int( ber, i, ber->ber_tag );
                     break;

              case 'e':     /* enumeration */
                     i = va_arg( ap, ber_int_t );
                     rc = ber_put_enum( ber, i, ber->ber_tag );
                     break;

              case 'n':     /* null */
                     rc = ber_put_null( ber, ber->ber_tag );
                     break;

              case 'N':     /* Debug NULL */
                     rc = 0;
                     if( lber_int_null != 0 ) {
                            /* Insert NULL to ensure peer ignores unknown tags */
                            rc = ber_put_null( ber, lber_int_null );
                     }
                     break;

              case 'o':     /* octet string (non-null terminated) */
                     s = va_arg( ap, char * );
                     len = va_arg( ap, ber_len_t );
                     rc = ber_put_ostring( ber, s, len, ber->ber_tag );
                     break;

              case 'O':     /* berval octet string */
                     bv = va_arg( ap, struct berval * );
                     if( bv == NULL ) break;
                     rc = ber_put_berval( ber, bv, ber->ber_tag );
                     break;

              case 's':     /* string */
                     s = va_arg( ap, char * );
                     rc = ber_put_string( ber, s, ber->ber_tag );
                     break;

              case 'B':     /* bit string */
              case 'X':     /* bit string (deprecated) */
                     s = va_arg( ap, char * );
                     len = va_arg( ap, ber_len_t );     /* in bits */
                     rc = ber_put_bitstring( ber, s, len, ber->ber_tag );
                     break;

              case 't':     /* tag for the next element */
                     ber->ber_tag = va_arg( ap, ber_tag_t );
                     goto next;

              case 'v':     /* vector of strings */
                     if ( (ss = va_arg( ap, char ** )) == NULL )
                            break;
                     for ( i = 0; ss[i] != NULL; i++ ) {
                            if ( (rc = ber_put_string( ber, ss[i],
                                ber->ber_tag )) == -1 )
                                   break;
                     }
                     break;

              case 'V':     /* sequences of strings + lengths */
                     if ( (bvp = va_arg( ap, struct berval ** )) == NULL )
                            break;
                     for ( i = 0; bvp[i] != NULL; i++ ) {
                            if ( (rc = ber_put_berval( ber, bvp[i],
                                ber->ber_tag )) == -1 )
                                   break;
                     }
                     break;

              case 'W':     /* BerVarray */
                     if ( (bv = va_arg( ap, BerVarray )) == NULL )
                            break;
                     for ( i = 0; bv[i].bv_val != NULL; i++ ) {
                            if ( (rc = ber_put_berval( ber, &bv[i],
                                ber->ber_tag )) == -1 )
                                   break;
                     }
                     break;

              case '{':     /* begin sequence */
                     rc = ber_start_seq( ber, ber->ber_tag );
                     break;

              case '}':     /* end sequence */
                     rc = ber_put_seqorset( ber );
                     break;

              case '[':     /* begin set */
                     rc = ber_start_set( ber, ber->ber_tag );
                     break;

              case ']':     /* end set */
                     rc = ber_put_seqorset( ber );
                     break;

              default:
                     if( ber->ber_debug ) {
                            ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug,
                                   "ber_printf: unknown fmt %c\n", *fmt );
                     }
                     rc = -1;
                     break;
              }

              ber->ber_tag = LBER_DEFAULT;
       next:;
       }

       va_end( ap );

       return rc;
}

Here is the call graph for this function:

int ber_put_berval ( BerElement *  ber,
struct berval bv,
ber_tag_t  tag 
)

Definition at line 253 of file encode.c.

{
       if( bv == NULL || bv->bv_len == 0 ) {
              return ber_put_ostring( ber, "", (ber_len_t) 0, tag );
       }

       return ber_put_ostring( ber, bv->bv_val, bv->bv_len, tag );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ber_put_bitstring ( BerElement *  ber,
LDAP_CONST char *  str,
ber_len_t  blen,
ber_tag_t  tag 
)

Definition at line 277 of file encode.c.

{
       int rc;
       ber_len_t            len;
       unsigned char unusedbits, header[HEADER_SIZE + 1], *ptr;

       if ( tag == LBER_DEFAULT ) {
              tag = LBER_BITSTRING;
       }

       unusedbits = (unsigned char) -blen & 7;
       len = blen / 8 + (unusedbits != 0); /* (blen+7)/8 without overflow */
       if ( len >= MAXINT_BERSIZE ) {
              return -1;
       }

       header[sizeof(header) - 1] = unusedbits;
       ptr = ber_prepend_len( &header[sizeof(header) - 1], len + 1 );
       ptr = ber_prepend_tag( ptr, tag );

       rc = ber_write( ber, (char *) ptr, &header[sizeof(header)] - ptr, 0 );
       if ( rc >= 0 && ber_write( ber, str, len, 0 ) >= 0 ) {
              /* length(tag + length + unused bit count + bitstring) */
              return rc + (int) len;
       }

       return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ber_put_boolean ( BerElement *  ber,
ber_int_t  boolval,
ber_tag_t  tag 
)

Definition at line 326 of file encode.c.

{
       unsigned char data[TAGBUF_SIZE + 2], *ptr;

       if ( tag == LBER_DEFAULT )
              tag = LBER_BOOLEAN;

       data[sizeof(data) - 1] = boolval ? 0xff : 0;
       data[sizeof(data) - 2] = 1;               /* length */
       ptr = ber_prepend_tag( &data[sizeof(data) - 2], tag );

       return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ber_put_enum ( BerElement *  ber,
ber_int_t  num,
ber_tag_t  tag 
)

Definition at line 197 of file encode.c.

{
       if ( tag == LBER_DEFAULT ) {
              tag = LBER_ENUMERATED;
       }

       return ber_put_int_or_enum( ber, num, tag );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ber_put_int ( BerElement *  ber,
ber_int_t  num,
ber_tag_t  tag 
)

Definition at line 210 of file encode.c.

{
       if ( tag == LBER_DEFAULT ) {
              tag = LBER_INTEGER;
       }

       return ber_put_int_or_enum( ber, num, tag );
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ber_put_int_or_enum ( BerElement *  ber,
ber_int_t  num,
ber_tag_t  tag 
) [static]

Definition at line 170 of file encode.c.

{
       ber_uint_t unum;
       unsigned char sign, data[TAGBUF_SIZE+1 + OCTET_SIZE(ber_int_t)], *ptr;

       sign = 0;
       unum = num;   /* Bit fiddling should be done with unsigned values */
       if ( num < 0 ) {
              sign = 0xffU;
              unum = ~unum;
       }
       for ( ptr = &data[sizeof(data) - 1] ;; unum >>= 8 ) {
              *ptr-- = (sign ^ (unsigned char) unum) & 0xffU;
              if ( unum < 0x80 )   /* top bit at *ptr is sign bit */
                     break;
       }

       *ptr = (unsigned char) (&data[sizeof(data) - 1] - ptr); /* length */
       ptr = ber_prepend_tag( ptr, tag );

       return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ber_put_null ( BerElement *  ber,
ber_tag_t  tag 
)

Definition at line 311 of file encode.c.

{
       unsigned char data[TAGBUF_SIZE + 1], *ptr;

       if ( tag == LBER_DEFAULT ) {
              tag = LBER_NULL;
       }

       data[sizeof(data) - 1] = 0;               /* length */
       ptr = ber_prepend_tag( &data[sizeof(data) - 1], tag );

       return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ber_put_ostring ( BerElement *  ber,
LDAP_CONST char *  str,
ber_len_t  len,
ber_tag_t  tag 
)

Definition at line 223 of file encode.c.

{
       int rc;
       unsigned char header[HEADER_SIZE], *ptr;

       if ( tag == LBER_DEFAULT ) {
              tag = LBER_OCTETSTRING;
       }

       if ( len > MAXINT_BERSIZE ) {
              return -1;
       }

       ptr = ber_prepend_len( &header[sizeof(header)], len );
       ptr = ber_prepend_tag( ptr, tag );

       rc = ber_write( ber, (char *) ptr, &header[sizeof(header)] - ptr, 0 );
       if ( rc >= 0 && ber_write( ber, str, len, 0 ) >= 0 ) {
              /* length(tag + length + contents) */
              return rc + (int) len;
       }

       return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ber_put_seq ( BerElement *  ber)

Definition at line 486 of file encode.c.

{
       return ber_put_seqorset( ber );
}

Here is the call graph for this function:

static int ber_put_seqorset ( BerElement *  ber) [static]

Definition at line 435 of file encode.c.

{
       Seqorset_header      header;
       unsigned char *lenptr;      /* length octets in the sequence/set */
       ber_len_t            len;          /* length(contents) */
       ber_len_t            xlen;         /* len + length(length) */

       assert( ber != NULL );
       assert( LBER_VALID( ber ) );

       if ( ber->ber_sos_ptr == NULL ) return -1;

       lenptr = (unsigned char *) ber->ber_buf + ber->ber_sos_inner;
       xlen = ber->ber_sos_ptr - (char *) lenptr;
       if ( xlen > MAXINT_BERSIZE + SOS_LENLEN ) {
              return -1;
       }

       /* Extract sequence/set information from length octets */
       memcpy( SOS_TAG_END(header), lenptr, SOS_LENLEN );

       /* Store length, and close gap of leftover reserved length octets */
       len = xlen - SOS_LENLEN;
       if ( !(ber->ber_options & LBER_USE_DER) ) {
              int i;
              lenptr[0] = SOS_LENLEN - 1 + 0x80; /* length(length)-1 */
              for( i = SOS_LENLEN; --i > 0; len >>= 8 ) {
                     lenptr[i] = len & 0xffU;
              }
       } else {
              unsigned char *p = ber_prepend_len( lenptr + SOS_LENLEN, len );
              ber_len_t unused = p - lenptr;
              if ( unused != 0 ) {
                     /* length(length) < the reserved SOS_LENLEN bytes */
                     xlen -= unused;
                     AC_MEMCPY( lenptr, p, xlen );
                     ber->ber_sos_ptr = (char *) lenptr + xlen;
              }
       }

       ber->ber_sos_inner = header.next_sos.offset;
       if ( header.next_sos.offset == 0 ) { /* outermost sequence/set? */
              /* The ber_ptr is at the set/seq start - move it to the end */
              ber->ber_ptr = ber->ber_sos_ptr;
              ber->ber_sos_ptr = NULL;
       }

       return xlen + *SOS_TAG_END(header); /* lenlen + len + taglen */
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ber_put_set ( BerElement *  ber)

Definition at line 492 of file encode.c.

{
       return ber_put_seqorset( ber );
}

Here is the call graph for this function:

int ber_put_string ( BerElement *  ber,
LDAP_CONST char *  str,
ber_tag_t  tag 
)

Definition at line 266 of file encode.c.

{
       assert( str != NULL );

       return ber_put_ostring( ber, str, strlen( str ), tag );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ber_start_seq ( BerElement *  ber,
ber_tag_t  tag 
)

Definition at line 414 of file encode.c.

{
       if ( tag == LBER_DEFAULT ) {
              tag = LBER_SEQUENCE;
       }

       return ber_start_seqorset( ber, tag );
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ber_start_seqorset ( BerElement *  ber,
ber_tag_t  tag 
) [static]

Definition at line 360 of file encode.c.

{
       /*
        * Write the tag and SOS_LENLEN octets reserved for length, to ber.
        * For now, length octets = (tag length, previous ber_sos_inner).
        *
        * Update ber_sos_inner and the write-cursor ber_sos_ptr.  ber_ptr
        * will not move until the outermost sequence or set is complete.
        */

       Seqorset_header      header;
       unsigned char *headptr;
       ber_len_t            taglen, headlen;
       char                 *dest, **p;

       assert( ber != NULL );
       assert( LBER_VALID( ber ) );

       if ( ber->ber_sos_ptr == NULL ) {  /* outermost sequence/set? */
              header.next_sos.offset = 0;
              p = &ber->ber_ptr;
       } else {
              if ( (ber_len_t) -1 > (ber_elem_size_t) -1 ) {
                     if ( ber->ber_sos_inner > (ber_elem_size_t) -1 )
                            return -1;
              }
              header.next_sos.offset = ber->ber_sos_inner;
              p = &ber->ber_sos_ptr;
       }
       headptr = ber_prepend_tag( SOS_TAG_END(header), tag );
       *SOS_TAG_END(header) = taglen = SOS_TAG_END(header) - headptr;
       headlen = taglen + SOS_LENLEN;

       /* As ber_write(,headptr,headlen,) except update ber_sos_ptr, not *p */
       if ( headlen > (ber_len_t) (ber->ber_end - *p) ) {
              if ( ber_realloc( ber, headlen ) != 0 )
                     return -1;
       }
       dest = *p;
       AC_MEMCPY( dest, headptr, headlen );
       ber->ber_sos_ptr = dest + headlen;

       ber->ber_sos_inner = dest + taglen - ber->ber_buf;

       /*
        * Do not return taglen + SOS_LENLEN here - then ber_put_seqorset()
        * should return lenlen - SOS_LENLEN + len, which can be < 0.
        */
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ber_start_set ( BerElement *  ber,
ber_tag_t  tag 
)

Definition at line 424 of file encode.c.

{
       if ( tag == LBER_DEFAULT ) {
              tag = LBER_SET;
       }

       return ber_start_seqorset( ber, tag );
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

ber_tag_t lber_int_null = 0 [static]

Definition at line 498 of file encode.c.