/* Resize the ber buffer */ int ber_realloc( BerElement *ber, ber_len_t len ) { ber_len_t total, offset, sos_offset; char *buf; assert( ber != NULL ); assert( LBER_VALID( ber ) ); /* leave room for ber_flatten() to \0-terminate ber_buf */ if ( ++len == 0 ) { return( -1 ); } total = ber_pvt_ber_total( ber ); #define LBER_EXBUFSIZ 4060 /* a few words less than 2^N for binary buddy */ #if defined( LBER_EXBUFSIZ ) && LBER_EXBUFSIZ > 0 # ifndef notdef /* don't realloc by small amounts */ total += len < LBER_EXBUFSIZ ? LBER_EXBUFSIZ : len; # else { /* not sure what value this adds. reduce fragmentation? */ ber_len_t have = (total + (LBER_EXBUFSIZE - 1)) / LBER_EXBUFSIZ; ber_len_t need = (len + (LBER_EXBUFSIZ - 1)) / LBER_EXBUFSIZ; total = ( have + need ) * LBER_EXBUFSIZ; } # endif #else total += len; /* realloc just what's needed */ #endif if ( total < len || total > (ber_len_t)-1 / 2 /* max ber_slen_t */ ) { return( -1 ); } buf = ber->ber_buf; offset = ber->ber_ptr - buf; sos_offset = ber->ber_sos_ptr ? ber->ber_sos_ptr - buf : 0; /* if ber_sos_ptr != NULL, it is > ber_buf so that sos_offset > 0 */ buf = (char *) ber_memrealloc_x( buf, total, ber->ber_memctx ); if ( buf == NULL ) { return( -1 ); } ber->ber_buf = buf; ber->ber_end = buf + total; ber->ber_ptr = buf + offset; if ( sos_offset ) ber->ber_sos_ptr = buf + sos_offset; return( 0 ); }
static int OpenLDAPaciNormalizeRights( struct berval *actions, struct berval *nactions, void *ctx ) { struct berval bv = BER_BVNULL; int i; BER_BVZERO( nactions ); for ( i = 0; acl_get_part( actions, i, '$', &bv ) >= 0; i++ ) { int rc; struct berval nbv; rc = OpenLDAPaciNormalizeRight( &bv, &nbv, ctx ); if ( rc != LDAP_SUCCESS ) { ber_memfree_x( nactions->bv_val, ctx ); BER_BVZERO( nactions ); return LDAP_INVALID_SYNTAX; } if ( i == 0 ) { *nactions = nbv; } else { nactions->bv_val = ber_memrealloc_x( nactions->bv_val, nactions->bv_len + STRLENOF( "$" ) + nbv.bv_len + 1, ctx ); nactions->bv_val[ nactions->bv_len ] = '$'; memcpy( &nactions->bv_val[ nactions->bv_len + 1 ], nbv.bv_val, nbv.bv_len + 1 ); ber_memfree_x( nbv.bv_val, ctx ); nactions->bv_len += STRLENOF( "$" ) + nbv.bv_len; } BER_BVZERO( &nbv ); } return LDAP_SUCCESS; }
static int OpenLDAPaciNormalizeRight( struct berval *action, struct berval *naction, void *ctx ) { struct berval grantdeny, perms = BER_BVNULL, bv = BER_BVNULL; int idx, i; /* grant|deny */ if ( acl_get_part( action, 0, ';', &grantdeny ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: missing ';' in '%s'\n", action->bv_val ); return LDAP_INVALID_SYNTAX; } idx = bv_getcaseidx( &grantdeny, ACIgrantdeny ); if ( idx == -1 ) { Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: '%s' must be grant or deny\n", grantdeny.bv_val ); return LDAP_INVALID_SYNTAX; } ber_dupbv_x( naction, (struct berval *)ACIgrantdeny[ idx ], ctx ); for ( i = 1; acl_get_part( action, i, ';', &bv ) >= 0; i++ ) { struct berval nattrs = BER_BVNULL; int freenattrs = 1; if ( i & 1 ) { /* perms */ if ( OpenLDAPaciValidatePerms( &bv ) != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } perms = bv; } else { /* attr */ char *ptr; /* could be "[all]" or an attribute description */ if ( ber_bvstrcasecmp( &bv, &aci_bv[ ACI_BV_BR_ALL ] ) == 0 ) { nattrs = aci_bv[ ACI_BV_BR_ALL ]; freenattrs = 0; } else { AttributeDescription *ad = NULL; AttributeDescription adstatic= { 0 }; const char *text = NULL; struct berval attr, left, right; int j; int len; for ( j = 0; acl_get_part( &bv, j, ',', &attr ) >= 0; j++ ) { ad = NULL; text = NULL; /* openldap 2.1 aci compabitibility [entry] -> entry */ if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_ENTRY ] ) == 0 ) { ad = &adstatic; adstatic.ad_cname = aci_bv[ ACI_BV_ENTRY ]; /* openldap 2.1 aci compabitibility [children] -> children */ } else if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_CHILDREN ] ) == 0 ) { ad = &adstatic; adstatic.ad_cname = aci_bv[ ACI_BV_CHILDREN ]; /* openldap 2.1 aci compabitibility [all] -> only [all] */ } else if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_ALL ] ) == 0 ) { ber_memfree_x( nattrs.bv_val, ctx ); nattrs = aci_bv[ ACI_BV_BR_ALL ]; freenattrs = 0; break; } else if ( acl_get_part( &attr, 0, '=', &left ) < 0 || acl_get_part( &attr, 1, '=', &right ) < 0 ) { if ( slap_bv2ad( &attr, &ad, &text ) != LDAP_SUCCESS ) { ber_memfree_x( nattrs.bv_val, ctx ); Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: unknown attribute: '%s'\n", attr.bv_val ); return LDAP_INVALID_SYNTAX; } } else { if ( slap_bv2ad( &left, &ad, &text ) != LDAP_SUCCESS ) { ber_memfree_x( nattrs.bv_val, ctx ); Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: unknown attribute: '%s'\n", left.bv_val ); return LDAP_INVALID_SYNTAX; } } len = nattrs.bv_len + ( !BER_BVISEMPTY( &nattrs ) ? STRLENOF( "," ) : 0 ) + ad->ad_cname.bv_len; nattrs.bv_val = ber_memrealloc_x( nattrs.bv_val, len + 1, ctx ); ptr = &nattrs.bv_val[ nattrs.bv_len ]; if ( !BER_BVISEMPTY( &nattrs ) ) { *ptr++ = ','; } ptr = lutil_strncopy( ptr, ad->ad_cname.bv_val, ad->ad_cname.bv_len ); ptr[ 0 ] = '\0'; nattrs.bv_len = len; } } naction->bv_val = ber_memrealloc_x( naction->bv_val, naction->bv_len + STRLENOF( ";" ) + perms.bv_len + STRLENOF( ";" ) + nattrs.bv_len + 1, ctx ); ptr = &naction->bv_val[ naction->bv_len ]; ptr[ 0 ] = ';'; ptr++; ptr = lutil_strncopy( ptr, perms.bv_val, perms.bv_len ); ptr[ 0 ] = ';'; ptr++; ptr = lutil_strncopy( ptr, nattrs.bv_val, nattrs.bv_len ); ptr[ 0 ] = '\0'; naction->bv_len += STRLENOF( ";" ) + perms.bv_len + STRLENOF( ";" ) + nattrs.bv_len; if ( freenattrs ) { ber_memfree_x( nattrs.bv_val, ctx ); } } } /* perms;attr go in pairs */ if ( i > 1 && ( i & 1 ) ) { return LDAP_SUCCESS; } else { Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: perms:attr need to be pairs in '%s'\n", action->bv_val ); return LDAP_INVALID_SYNTAX; } }
struct berbuf * backsql_strcat_x( struct berbuf *dest, void *memctx, ... ) { va_list strs; ber_len_t cdlen, cslen, grow; char *cstr; assert( dest != NULL ); assert( dest->bb_val.bv_val == NULL || dest->bb_val.bv_len == strlen( dest->bb_val.bv_val ) ); #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "==>backsql_strcat()\n", 0, 0, 0 ); #endif /* BACKSQL_TRACE */ va_start( strs, memctx ); if ( dest->bb_val.bv_val == NULL || dest->bb_len == 0 ) { dest->bb_val.bv_val = (char *)ber_memalloc_x( BACKSQL_STR_GROW * sizeof( char ), memctx ); dest->bb_val.bv_len = 0; dest->bb_len = BACKSQL_STR_GROW; } cdlen = dest->bb_val.bv_len; while ( ( cstr = va_arg( strs, char * ) ) != NULL ) { cslen = strlen( cstr ); grow = BACKSQL_MAX( BACKSQL_STR_GROW, cslen ); if ( dest->bb_len - cdlen <= cslen ) { char *tmp_dest; #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_strcat(): " "buflen=%d, cdlen=%d, cslen=%d " "-- reallocating dest\n", dest->bb_len, cdlen + 1, cslen ); #endif /* BACKSQL_TRACE */ tmp_dest = (char *)ber_memrealloc_x( dest->bb_val.bv_val, dest->bb_len + grow * sizeof( char ), memctx ); if ( tmp_dest == NULL ) { Debug( LDAP_DEBUG_ANY, "backsql_strcat(): " "could not reallocate string buffer.\n", 0, 0, 0 ); return NULL; } dest->bb_val.bv_val = tmp_dest; dest->bb_len += grow; #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_strcat(): " "new buflen=%d, dest=%p\n", dest->bb_len, dest, 0 ); #endif /* BACKSQL_TRACE */ } AC_MEMCPY( dest->bb_val.bv_val + cdlen, cstr, cslen + 1 ); cdlen += cslen; } va_end( strs ); #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "<==backsql_strcat() (dest=\"%s\")\n", dest->bb_val.bv_val, 0, 0 ); #endif /* BACKSQL_TRACE */ dest->bb_val.bv_len = cdlen; return dest; }
struct berbuf * backsql_strfcat_x( struct berbuf *dest, void *memctx, const char *fmt, ... ) { va_list strs; ber_len_t cdlen; assert( dest != NULL ); assert( fmt != NULL ); assert( dest->bb_len == 0 || dest->bb_len > dest->bb_val.bv_len ); assert( dest->bb_val.bv_val == NULL || dest->bb_val.bv_len == strlen( dest->bb_val.bv_val ) ); #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "==>backsql_strfcat()\n", 0, 0, 0 ); #endif /* BACKSQL_TRACE */ va_start( strs, fmt ); if ( dest->bb_val.bv_val == NULL || dest->bb_len == 0 ) { dest->bb_val.bv_val = (char *)ber_memalloc_x( BACKSQL_STR_GROW * sizeof( char ), memctx ); dest->bb_val.bv_len = 0; dest->bb_len = BACKSQL_STR_GROW; } cdlen = dest->bb_val.bv_len; for ( ; fmt[0]; fmt++ ) { ber_len_t cslen, grow; char *cstr, cc[ 2 ] = { '\0', '\0' }; struct berval *cbv; switch ( fmt[ 0 ] ) { /* berval */ case 'b': cbv = va_arg( strs, struct berval * ); cstr = cbv->bv_val; cslen = cbv->bv_len; break; /* length + string */ case 'l': cslen = va_arg( strs, ber_len_t ); cstr = va_arg( strs, char * ); break; /* string */ case 's': cstr = va_arg( strs, char * ); cslen = strlen( cstr ); break; /* char */ case 'c': /* * `char' is promoted to `int' when passed through `...' */ cc[0] = va_arg( strs, int ); cstr = cc; cslen = 1; break; default: assert( 0 ); } grow = BACKSQL_MAX( BACKSQL_STR_GROW, cslen ); if ( dest->bb_len - cdlen <= cslen ) { char *tmp_dest; #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_strfcat(): " "buflen=%d, cdlen=%d, cslen=%d " "-- reallocating dest\n", dest->bb_len, cdlen + 1, cslen ); #endif /* BACKSQL_TRACE */ tmp_dest = (char *)ber_memrealloc_x( dest->bb_val.bv_val, ( dest->bb_len ) + grow * sizeof( char ), memctx ); if ( tmp_dest == NULL ) { Debug( LDAP_DEBUG_ANY, "backsql_strfcat(): " "could not reallocate string buffer.\n", 0, 0, 0 ); return NULL; } dest->bb_val.bv_val = tmp_dest; dest->bb_len += grow * sizeof( char ); #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_strfcat(): " "new buflen=%d, dest=%p\n", dest->bb_len, dest, 0 ); #endif /* BACKSQL_TRACE */ } assert( cstr != NULL ); AC_MEMCPY( dest->bb_val.bv_val + cdlen, cstr, cslen + 1 ); cdlen += cslen; } va_end( strs ); #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "<==backsql_strfcat() (dest=\"%s\")\n", dest->bb_val.bv_val, 0, 0 ); #endif /* BACKSQL_TRACE */ dest->bb_val.bv_len = cdlen; return dest; }
static int ldap_back_int_filter_map_rewrite( dncookie *dc, Filter *f, struct berval *fstr, int remap, void *memctx ) { int i; Filter *p; struct berval atmp, vtmp, *tmp; static struct berval /* better than nothing... */ ber_bvfalse = BER_BVC( "(!(objectClass=*))" ), ber_bvtf_false = BER_BVC( "(|)" ), /* better than nothing... */ ber_bvtrue = BER_BVC( "(objectClass=*)" ), ber_bvtf_true = BER_BVC( "(&)" ), #if 0 /* no longer needed; preserved for completeness */ ber_bvundefined = BER_BVC( "(?=undefined)" ), #endif ber_bverror = BER_BVC( "(?=error)" ), ber_bvunknown = BER_BVC( "(?=unknown)" ), ber_bvnone = BER_BVC( "(?=none)" ); ber_len_t len; assert( fstr != NULL ); BER_BVZERO( fstr ); if ( f == NULL ) { ber_dupbv_x( fstr, &ber_bvnone, memctx ); return LDAP_OTHER; } switch ( ( f->f_choice & SLAPD_FILTER_MASK ) ) { case LDAP_FILTER_EQUALITY: if ( map_attr_value( dc, f->f_av_desc, &atmp, &f->f_av_value, &vtmp, remap, memctx ) ) { goto computed; } fstr->bv_len = atmp.bv_len + vtmp.bv_len + ( sizeof("(=)") - 1 ); fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)", atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); ber_memfree_x( vtmp.bv_val, memctx ); break; case LDAP_FILTER_GE: if ( map_attr_value( dc, f->f_av_desc, &atmp, &f->f_av_value, &vtmp, remap, memctx ) ) { goto computed; } fstr->bv_len = atmp.bv_len + vtmp.bv_len + ( sizeof("(>=)") - 1 ); fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)", atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); ber_memfree_x( vtmp.bv_val, memctx ); break; case LDAP_FILTER_LE: if ( map_attr_value( dc, f->f_av_desc, &atmp, &f->f_av_value, &vtmp, remap, memctx ) ) { goto computed; } fstr->bv_len = atmp.bv_len + vtmp.bv_len + ( sizeof("(<=)") - 1 ); fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)", atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); ber_memfree_x( vtmp.bv_val, memctx ); break; case LDAP_FILTER_APPROX: if ( map_attr_value( dc, f->f_av_desc, &atmp, &f->f_av_value, &vtmp, remap, memctx ) ) { goto computed; } fstr->bv_len = atmp.bv_len + vtmp.bv_len + ( sizeof("(~=)") - 1 ); fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)", atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); ber_memfree_x( vtmp.bv_val, memctx ); break; case LDAP_FILTER_SUBSTRINGS: if ( map_attr_value( dc, f->f_sub_desc, &atmp, NULL, NULL, remap, memctx ) ) { goto computed; } /* cannot be a DN ... */ fstr->bv_len = atmp.bv_len + ( STRLENOF( "(=*)" ) ); fstr->bv_val = ber_memalloc_x( fstr->bv_len + 128, memctx ); /* FIXME: why 128 ? */ snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)", atmp.bv_val ); if ( !BER_BVISNULL( &f->f_sub_initial ) ) { len = fstr->bv_len; filter_escape_value_x( &f->f_sub_initial, &vtmp, memctx ); fstr->bv_len += vtmp.bv_len; fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx ); snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3, /* "(attr=" */ "%s*)", vtmp.bv_len ? vtmp.bv_val : "" ); ber_memfree_x( vtmp.bv_val, memctx ); } if ( f->f_sub_any != NULL ) { for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) { len = fstr->bv_len; filter_escape_value_x( &f->f_sub_any[i], &vtmp, memctx ); fstr->bv_len += vtmp.bv_len + 1; fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx ); snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3, /* "(attr=[init]*[any*]" */ "%s*)", vtmp.bv_len ? vtmp.bv_val : "" ); ber_memfree_x( vtmp.bv_val, memctx ); } } if ( !BER_BVISNULL( &f->f_sub_final ) ) { len = fstr->bv_len; filter_escape_value_x( &f->f_sub_final, &vtmp, memctx ); fstr->bv_len += vtmp.bv_len; fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx ); snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3, /* "(attr=[init*][any*]" */ "%s)", vtmp.bv_len ? vtmp.bv_val : "" ); ber_memfree_x( vtmp.bv_val, memctx ); } break; case LDAP_FILTER_PRESENT: if ( map_attr_value( dc, f->f_desc, &atmp, NULL, NULL, remap, memctx ) ) { goto computed; } fstr->bv_len = atmp.bv_len + ( STRLENOF( "(=*)" ) ); fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)", atmp.bv_val ); break; case LDAP_FILTER_AND: case LDAP_FILTER_OR: case LDAP_FILTER_NOT: fstr->bv_len = STRLENOF( "(%)" ); fstr->bv_val = ber_memalloc_x( fstr->bv_len + 128, memctx ); /* FIXME: why 128? */ snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)", f->f_choice == LDAP_FILTER_AND ? '&' : f->f_choice == LDAP_FILTER_OR ? '|' : '!' ); for ( p = f->f_list; p != NULL; p = p->f_next ) { int rc; len = fstr->bv_len; rc = ldap_back_int_filter_map_rewrite( dc, p, &vtmp, remap, memctx ); if ( rc != LDAP_SUCCESS ) { return rc; } fstr->bv_len += vtmp.bv_len; fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx ); snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" ); ber_memfree_x( vtmp.bv_val, memctx ); } break; case LDAP_FILTER_EXT: if ( f->f_mr_desc ) { if ( map_attr_value( dc, f->f_mr_desc, &atmp, &f->f_mr_value, &vtmp, remap, memctx ) ) { goto computed; } } else { BER_BVSTR( &atmp, "" ); filter_escape_value_x( &f->f_mr_value, &vtmp, memctx ); } /* FIXME: cleanup (less ?: operators...) */ fstr->bv_len = atmp.bv_len + ( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) + ( !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_len + 1 : 0 ) + vtmp.bv_len + ( STRLENOF( "(:=)" ) ); fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)", atmp.bv_val, f->f_mr_dnattrs ? ":dn" : "", !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "", !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "", vtmp.bv_len ? vtmp.bv_val : "" ); ber_memfree_x( vtmp.bv_val, memctx ); break; case SLAPD_FILTER_COMPUTED: switch ( f->f_result ) { /* FIXME: treat UNDEFINED as FALSE */ case SLAPD_COMPARE_UNDEFINED: computed:; if ( META_BACK_TGT_NOUNDEFFILTER( dc->target ) ) { return LDAP_COMPARE_FALSE; } /* fallthru */ case LDAP_COMPARE_FALSE: if ( META_BACK_TGT_T_F( dc->target ) ) { tmp = &ber_bvtf_false; break; } tmp = &ber_bvfalse; break; case LDAP_COMPARE_TRUE: if ( META_BACK_TGT_T_F( dc->target ) ) { tmp = &ber_bvtf_true; break; } tmp = &ber_bvtrue; break; default: tmp = &ber_bverror; break; } ber_dupbv_x( fstr, tmp, memctx ); break; default: ber_dupbv_x( fstr, &ber_bvunknown, memctx ); break; } return 0; }
struct berval * UTF8bvnormalize( struct berval *bv, struct berval *newbv, unsigned flags, void *ctx ) { int i, j, len, clen, outpos, ucsoutlen, outsize, last; int didnewbv = 0; char *out, *outtmp, *s; ac_uint4 *ucs, *p, *ucsout; static unsigned char mask[] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; unsigned casefold = flags & LDAP_UTF8_CASEFOLD; unsigned approx = flags & LDAP_UTF8_APPROX; if ( bv == NULL ) { return NULL; } s = bv->bv_val; len = bv->bv_len; if ( len == 0 ) { return ber_dupbv_x( newbv, bv, ctx ); } if ( !newbv ) { newbv = ber_memalloc_x( sizeof(struct berval), ctx ); if ( !newbv ) return NULL; didnewbv = 1; } /* Should first check to see if string is already in proper * normalized form. This is almost as time consuming as * the normalization though. */ /* finish off everything up to character before first non-ascii */ if ( LDAP_UTF8_ISASCII( s ) ) { if ( casefold ) { outsize = len + 7; out = (char *) ber_memalloc_x( outsize, ctx ); if ( out == NULL ) { fail: if ( didnewbv ) ber_memfree_x( newbv, ctx ); return NULL; } outpos = 0; for ( i = 1; (i < len) && LDAP_UTF8_ISASCII(s + i); i++ ) { out[outpos++] = TOLOWER( s[i-1] ); } if ( i == len ) { out[outpos++] = TOLOWER( s[len-1] ); out[outpos] = '\0'; newbv->bv_val = out; newbv->bv_len = outpos; return newbv; } } else { for ( i = 1; (i < len) && LDAP_UTF8_ISASCII(s + i); i++ ) { /* empty */ } if ( i == len ) { return ber_str2bv_x( s, len, 1, newbv, ctx ); } outsize = len + 7; out = (char *) ber_memalloc_x( outsize, ctx ); if ( out == NULL ) { goto fail; } outpos = i - 1; memcpy(out, s, outpos); } } else { outsize = len + 7; out = (char *) ber_memalloc_x( outsize, ctx ); if ( out == NULL ) { goto fail; } outpos = 0; i = 0; } p = ucs = ber_memalloc_x( len * sizeof(*ucs), ctx ); if ( ucs == NULL ) { ber_memfree_x(out, ctx); goto fail; } /* convert character before first non-ascii to ucs-4 */ if ( i > 0 ) { *p = casefold ? TOLOWER( s[i-1] ) : s[i-1]; p++; } /* s[i] is now first non-ascii character */ for (;;) { /* s[i] is non-ascii */ /* convert everything up to next ascii to ucs-4 */ while ( i < len ) { clen = LDAP_UTF8_CHARLEN2( s + i, clen ); if ( clen == 0 ) { ber_memfree_x( ucs, ctx ); ber_memfree_x( out, ctx ); goto fail; } if ( clen == 1 ) { /* ascii */ break; } *p = s[i] & mask[clen]; i++; for( j = 1; j < clen; j++ ) { if ( (s[i] & 0xc0) != 0x80 ) { ber_memfree_x( ucs, ctx ); ber_memfree_x( out, ctx ); goto fail; } *p <<= 6; *p |= s[i] & 0x3f; i++; } if ( casefold ) { *p = uctolower( *p ); } p++; } /* normalize ucs of length p - ucs */ uccompatdecomp( ucs, p - ucs, &ucsout, &ucsoutlen, ctx ); if ( approx ) { for ( j = 0; j < ucsoutlen; j++ ) { if ( ucsout[j] < 0x80 ) { out[outpos++] = ucsout[j]; } } } else { ucsoutlen = uccanoncomp( ucsout, ucsoutlen ); /* convert ucs to utf-8 and store in out */ for ( j = 0; j < ucsoutlen; j++ ) { /* allocate more space if not enough room for 6 bytes and terminator */ if ( outsize - outpos < 7 ) { outsize = ucsoutlen - j + outpos + 6; outtmp = (char *) ber_memrealloc_x( out, outsize, ctx ); if ( outtmp == NULL ) { ber_memfree_x( ucsout, ctx ); ber_memfree_x( ucs, ctx ); ber_memfree_x( out, ctx ); goto fail; } out = outtmp; } outpos += ldap_x_ucs4_to_utf8( ucsout[j], &out[outpos] ); } } ber_memfree_x( ucsout, ctx ); ucsout = NULL; if ( i == len ) { break; } last = i; /* Allocate more space in out if necessary */ if (len - i >= outsize - outpos) { outsize += 1 + ((len - i) - (outsize - outpos)); outtmp = (char *) ber_memrealloc_x(out, outsize, ctx); if (outtmp == NULL) { ber_memfree_x( ucs, ctx ); ber_memfree_x( out, ctx ); goto fail; } out = outtmp; } /* s[i] is ascii */ /* finish off everything up to char before next non-ascii */ for ( i++; (i < len) && LDAP_UTF8_ISASCII(s + i); i++ ) { out[outpos++] = casefold ? TOLOWER( s[i-1] ) : s[i-1]; } if ( i == len ) { out[outpos++] = casefold ? TOLOWER( s[len-1] ) : s[len-1]; break; } /* convert character before next non-ascii to ucs-4 */ *ucs = casefold ? TOLOWER( s[i-1] ) : s[i-1]; p = ucs + 1; } ber_memfree_x( ucs, ctx ); out[outpos] = '\0'; newbv->bv_val = out; newbv->bv_len = outpos; return newbv; }
int ber_realloc( BerElement *ber, ber_len_t len ) { ber_len_t total; Seqorset *s; long off; char *oldbuf; assert( ber != NULL ); assert( len > 0 ); assert( LBER_VALID( ber ) ); total = ber_pvt_ber_total( ber ); #define LBER_EXBUFSIZ 4060 /* a few words less than 2^N for binary buddy */ #if defined( LBER_EXBUFSIZ ) && LBER_EXBUFSIZ > 0 # ifndef notdef /* don't realloc by small amounts */ total += len < LBER_EXBUFSIZ ? LBER_EXBUFSIZ : len; # else { /* not sure what value this adds */ ber_len_t have = (total + (LBER_EXBUFSIZE - 1)) / LBER_EXBUFSIZ; ber_len_t need = (len + (LBER_EXBUFSIZ - 1)) / LBER_EXBUFSIZ; total = ( have + need ) * LBER_EXBUFSIZ; } # endif #else total += len; /* realloc just what's needed */ #endif oldbuf = ber->ber_buf; ber->ber_buf = (char *) ber_memrealloc_x( oldbuf, total, ber->ber_memctx ); if ( ber->ber_buf == NULL ) { ber->ber_buf = oldbuf; return( -1 ); } ber->ber_end = ber->ber_buf + total; /* * If the stinking thing was moved, we need to go through and * reset all the sos and ber pointers. Offsets would've been * a better idea... oh well. */ if ( ber->ber_buf != oldbuf ) { ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf); for ( s = ber->ber_sos; s != NULL; s = s->sos_next ) { off = s->sos_first - oldbuf; s->sos_first = ber->ber_buf + off; off = s->sos_ptr - oldbuf; s->sos_ptr = ber->ber_buf + off; } } return( 0 ); }