1 /* $NetBSD: getdn.c,v 1.1.1.6 2018/02/06 01:53:08 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2017 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17 /* Portions Copyright (c) 1994 Regents of the University of Michigan. 18 * All rights reserved. 19 */ 20 21 #include <sys/cdefs.h> 22 __RCSID("$NetBSD: getdn.c,v 1.1.1.6 2018/02/06 01:53:08 christos Exp $"); 23 24 #include "portable.h" 25 26 #include <stdio.h> 27 28 #include <ac/stdlib.h> 29 #include <ac/socket.h> 30 #include <ac/string.h> 31 #include <ac/time.h> 32 33 #include "ldap-int.h" 34 #include "ldap_schema.h" 35 36 /* extension to UFN that turns trailing "dc=value" rdns in DNS style, 37 * e.g. "ou=People,dc=openldap,dc=org" => "People, openldap.org" */ 38 #define DC_IN_UFN 39 40 /* parsing/printing routines */ 41 static int str2strval( const char *str, ber_len_t stoplen, struct berval *val, 42 const char **next, unsigned flags, int *retFlags, void *ctx ); 43 static int DCE2strval( const char *str, struct berval *val, 44 const char **next, unsigned flags, void *ctx ); 45 static int IA52strval( const char *str, struct berval *val, 46 const char **next, unsigned flags, void *ctx ); 47 static int quotedIA52strval( const char *str, struct berval *val, 48 const char **next, unsigned flags, void *ctx ); 49 static int hexstr2binval( const char *str, struct berval *val, 50 const char **next, unsigned flags, void *ctx ); 51 static int hexstr2bin( const char *str, char *c ); 52 static int byte2hexpair( const char *val, char *pair ); 53 static int binval2hexstr( struct berval *val, char *str ); 54 static int strval2strlen( struct berval *val, unsigned flags, 55 ber_len_t *len ); 56 static int strval2str( struct berval *val, char *str, unsigned flags, 57 ber_len_t *len ); 58 static int strval2IA5strlen( struct berval *val, unsigned flags, 59 ber_len_t *len ); 60 static int strval2IA5str( struct berval *val, char *str, unsigned flags, 61 ber_len_t *len ); 62 static int strval2DCEstrlen( struct berval *val, unsigned flags, 63 ber_len_t *len ); 64 static int strval2DCEstr( struct berval *val, char *str, unsigned flags, 65 ber_len_t *len ); 66 static int strval2ADstrlen( struct berval *val, unsigned flags, 67 ber_len_t *len ); 68 static int strval2ADstr( struct berval *val, char *str, unsigned flags, 69 ber_len_t *len ); 70 static int dn2domain( LDAPDN dn, struct berval *bv, int pos, int *iRDN ); 71 72 /* AVA helpers */ 73 static LDAPAVA * ldapava_new( 74 const struct berval *attr, const struct berval *val, unsigned flags, void *ctx ); 75 76 /* Higher level helpers */ 77 static int rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len, 78 int ( *s2l )( struct berval *, unsigned, ber_len_t * ) ); 79 static int rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, 80 int ( *s2s )( struct berval *, char *, unsigned, ber_len_t * )); 81 static int rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ); 82 static int rdn2UFNstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len ); 83 static int rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ); 84 static int rdn2DCEstr( LDAPRDN rdn, char *str, unsigned flag, ber_len_t *len, int first ); 85 static int rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ); 86 static int rdn2ADstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first ); 87 88 /* 89 * RFC 1823 ldap_get_dn 90 */ 91 char * 92 ldap_get_dn( LDAP *ld, LDAPMessage *entry ) 93 { 94 char *dn; 95 BerElement tmp; 96 97 Debug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 ); 98 99 assert( ld != NULL ); 100 assert( LDAP_VALID(ld) ); 101 assert( entry != NULL ); 102 103 tmp = *entry->lm_ber; /* struct copy */ 104 if ( ber_scanf( &tmp, "{a" /*}*/, &dn ) == LBER_ERROR ) { 105 ld->ld_errno = LDAP_DECODING_ERROR; 106 return( NULL ); 107 } 108 109 return( dn ); 110 } 111 112 int 113 ldap_get_dn_ber( LDAP *ld, LDAPMessage *entry, BerElement **berout, 114 BerValue *dn ) 115 { 116 BerElement tmp, *ber; 117 ber_len_t len = 0; 118 int rc = LDAP_SUCCESS; 119 120 Debug( LDAP_DEBUG_TRACE, "ldap_get_dn_ber\n", 0, 0, 0 ); 121 122 assert( ld != NULL ); 123 assert( LDAP_VALID(ld) ); 124 assert( entry != NULL ); 125 assert( dn != NULL ); 126 127 dn->bv_val = NULL; 128 dn->bv_len = 0; 129 130 if ( berout ) { 131 *berout = NULL; 132 ber = ldap_alloc_ber_with_options( ld ); 133 if( ber == NULL ) { 134 return LDAP_NO_MEMORY; 135 } 136 *berout = ber; 137 } else { 138 ber = &tmp; 139 } 140 141 *ber = *entry->lm_ber; /* struct copy */ 142 if ( ber_scanf( ber, "{ml{" /*}*/, dn, &len ) == LBER_ERROR ) { 143 rc = ld->ld_errno = LDAP_DECODING_ERROR; 144 } 145 if ( rc == LDAP_SUCCESS ) { 146 /* set the length to avoid overrun */ 147 rc = ber_set_option( ber, LBER_OPT_REMAINING_BYTES, &len ); 148 if( rc != LBER_OPT_SUCCESS ) { 149 rc = ld->ld_errno = LDAP_LOCAL_ERROR; 150 } 151 } 152 if ( rc != LDAP_SUCCESS && berout ) { 153 ber_free( ber, 0 ); 154 *berout = NULL; 155 } 156 return rc; 157 } 158 159 /* 160 * RFC 1823 ldap_dn2ufn 161 */ 162 char * 163 ldap_dn2ufn( LDAP_CONST char *dn ) 164 { 165 char *out = NULL; 166 167 Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 ); 168 169 ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, 170 &out, LDAP_DN_FORMAT_UFN ); 171 172 return( out ); 173 } 174 175 /* 176 * RFC 1823 ldap_explode_dn 177 */ 178 char ** 179 ldap_explode_dn( LDAP_CONST char *dn, int notypes ) 180 { 181 LDAPDN tmpDN; 182 char **values = NULL; 183 int iRDN; 184 unsigned flag = notypes ? LDAP_DN_FORMAT_UFN : LDAP_DN_FORMAT_LDAPV3; 185 186 Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 ); 187 188 if ( ldap_str2dn( dn, &tmpDN, LDAP_DN_FORMAT_LDAP ) 189 != LDAP_SUCCESS ) { 190 return NULL; 191 } 192 193 if( tmpDN == NULL ) { 194 values = LDAP_MALLOC( sizeof( char * ) ); 195 if( values == NULL ) return NULL; 196 197 values[0] = NULL; 198 return values; 199 } 200 201 for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ ); 202 203 values = LDAP_MALLOC( sizeof( char * ) * ( 1 + iRDN ) ); 204 if ( values == NULL ) { 205 ldap_dnfree( tmpDN ); 206 return NULL; 207 } 208 209 for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ ) { 210 ldap_rdn2str( tmpDN[ iRDN ], &values[ iRDN ], flag ); 211 } 212 ldap_dnfree( tmpDN ); 213 values[ iRDN ] = NULL; 214 215 return values; 216 } 217 218 char ** 219 ldap_explode_rdn( LDAP_CONST char *rdn, int notypes ) 220 { 221 LDAPRDN tmpRDN; 222 char **values = NULL; 223 const char *p; 224 int iAVA; 225 226 Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 ); 227 228 /* 229 * we only parse the first rdn 230 * FIXME: we prefer efficiency over checking if the _ENTIRE_ 231 * dn can be parsed 232 */ 233 if ( ldap_str2rdn( rdn, &tmpRDN, (char **) &p, LDAP_DN_FORMAT_LDAP ) 234 != LDAP_SUCCESS ) { 235 return( NULL ); 236 } 237 238 for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) ; 239 values = LDAP_MALLOC( sizeof( char * ) * ( 1 + iAVA ) ); 240 if ( values == NULL ) { 241 ldap_rdnfree( tmpRDN ); 242 return( NULL ); 243 } 244 245 for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) { 246 ber_len_t l = 0, vl, al = 0; 247 char *str; 248 LDAPAVA *ava = tmpRDN[ iAVA ]; 249 250 if ( ava->la_flags & LDAP_AVA_BINARY ) { 251 vl = 1 + 2 * ava->la_value.bv_len; 252 253 } else { 254 if ( strval2strlen( &ava->la_value, 255 ava->la_flags, &vl ) ) { 256 goto error_return; 257 } 258 } 259 260 if ( !notypes ) { 261 al = ava->la_attr.bv_len; 262 l = vl + ava->la_attr.bv_len + 1; 263 264 str = LDAP_MALLOC( l + 1 ); 265 AC_MEMCPY( str, ava->la_attr.bv_val, 266 ava->la_attr.bv_len ); 267 str[ al++ ] = '='; 268 269 } else { 270 l = vl; 271 str = LDAP_MALLOC( l + 1 ); 272 } 273 274 if ( ava->la_flags & LDAP_AVA_BINARY ) { 275 str[ al++ ] = '#'; 276 if ( binval2hexstr( &ava->la_value, &str[ al ] ) ) { 277 goto error_return; 278 } 279 280 } else { 281 if ( strval2str( &ava->la_value, &str[ al ], 282 ava->la_flags, &vl ) ) { 283 goto error_return; 284 } 285 } 286 287 str[ l ] = '\0'; 288 values[ iAVA ] = str; 289 } 290 values[ iAVA ] = NULL; 291 292 ldap_rdnfree( tmpRDN ); 293 294 return( values ); 295 296 error_return:; 297 LBER_VFREE( values ); 298 ldap_rdnfree( tmpRDN ); 299 return( NULL ); 300 } 301 302 char * 303 ldap_dn2dcedn( LDAP_CONST char *dn ) 304 { 305 char *out = NULL; 306 307 Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 ); 308 309 ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, 310 &out, LDAP_DN_FORMAT_DCE ); 311 312 return( out ); 313 } 314 315 char * 316 ldap_dcedn2dn( LDAP_CONST char *dce ) 317 { 318 char *out = NULL; 319 320 Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 ); 321 322 ( void )ldap_dn_normalize( dce, LDAP_DN_FORMAT_DCE, &out, LDAP_DN_FORMAT_LDAPV3 ); 323 324 return( out ); 325 } 326 327 char * 328 ldap_dn2ad_canonical( LDAP_CONST char *dn ) 329 { 330 char *out = NULL; 331 332 Debug( LDAP_DEBUG_TRACE, "ldap_dn2ad_canonical\n", 0, 0, 0 ); 333 334 ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, 335 &out, LDAP_DN_FORMAT_AD_CANONICAL ); 336 337 return( out ); 338 } 339 340 /* 341 * function that changes the string representation of dnin 342 * from ( fin & LDAP_DN_FORMAT_MASK ) to ( fout & LDAP_DN_FORMAT_MASK ) 343 * 344 * fin can be one of: 345 * LDAP_DN_FORMAT_LDAP (RFC 4514 liberal, plus some RFC 1779) 346 * LDAP_DN_FORMAT_LDAPV3 (RFC 4514) 347 * LDAP_DN_FORMAT_LDAPV2 (RFC 1779) 348 * LDAP_DN_FORMAT_DCE (?) 349 * 350 * fout can be any of the above except 351 * LDAP_DN_FORMAT_LDAP 352 * plus: 353 * LDAP_DN_FORMAT_UFN (RFC 1781, partial and with extensions) 354 * LDAP_DN_FORMAT_AD_CANONICAL (?) 355 */ 356 int 357 ldap_dn_normalize( LDAP_CONST char *dnin, 358 unsigned fin, char **dnout, unsigned fout ) 359 { 360 int rc; 361 LDAPDN tmpDN = NULL; 362 363 Debug( LDAP_DEBUG_TRACE, "ldap_dn_normalize\n", 0, 0, 0 ); 364 365 assert( dnout != NULL ); 366 367 *dnout = NULL; 368 369 if ( dnin == NULL ) { 370 return( LDAP_SUCCESS ); 371 } 372 373 rc = ldap_str2dn( dnin , &tmpDN, fin ); 374 if ( rc != LDAP_SUCCESS ) { 375 return( rc ); 376 } 377 378 rc = ldap_dn2str( tmpDN, dnout, fout ); 379 380 ldap_dnfree( tmpDN ); 381 382 return( rc ); 383 } 384 385 /* States */ 386 #define B4AVA 0x0000 387 388 /* #define B4ATTRTYPE 0x0001 */ 389 #define B4OIDATTRTYPE 0x0002 390 #define B4STRINGATTRTYPE 0x0003 391 392 #define B4AVAEQUALS 0x0100 393 #define B4AVASEP 0x0200 394 #define B4RDNSEP 0x0300 395 #define GOTAVA 0x0400 396 397 #define B4ATTRVALUE 0x0010 398 #define B4STRINGVALUE 0x0020 399 #define B4IA5VALUEQUOTED 0x0030 400 #define B4IA5VALUE 0x0040 401 #define B4BINARYVALUE 0x0050 402 403 /* 404 * Helpers (mostly from slap.h) 405 * c is assumed to Unicode in an ASCII compatible format (UTF-8) 406 * Macros assume "C" Locale (ASCII) 407 */ 408 #define LDAP_DN_ASCII_SPACE(c) \ 409 ( (c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' ) 410 #define LDAP_DN_ASCII_LOWER(c) LDAP_LOWER(c) 411 #define LDAP_DN_ASCII_UPPER(c) LDAP_UPPER(c) 412 #define LDAP_DN_ASCII_ALPHA(c) LDAP_ALPHA(c) 413 414 #define LDAP_DN_ASCII_DIGIT(c) LDAP_DIGIT(c) 415 #define LDAP_DN_ASCII_LCASE_HEXALPHA(c) LDAP_HEXLOWER(c) 416 #define LDAP_DN_ASCII_UCASE_HEXALPHA(c) LDAP_HEXUPPER(c) 417 #define LDAP_DN_ASCII_HEXDIGIT(c) LDAP_HEX(c) 418 #define LDAP_DN_ASCII_ALNUM(c) LDAP_ALNUM(c) 419 #define LDAP_DN_ASCII_PRINTABLE(c) ( (c) >= ' ' && (c) <= '~' ) 420 421 /* attribute type */ 422 #define LDAP_DN_OID_LEADCHAR(c) LDAP_DIGIT(c) 423 #define LDAP_DN_DESC_LEADCHAR(c) LDAP_ALPHA(c) 424 #define LDAP_DN_DESC_CHAR(c) LDAP_LDH(c) 425 #define LDAP_DN_LANG_SEP(c) ( (c) == ';' ) 426 #define LDAP_DN_ATTRDESC_CHAR(c) \ 427 ( LDAP_DN_DESC_CHAR(c) || LDAP_DN_LANG_SEP(c) ) 428 429 /* special symbols */ 430 #define LDAP_DN_AVA_EQUALS(c) ( (c) == '=' ) 431 #define LDAP_DN_AVA_SEP(c) ( (c) == '+' ) 432 #define LDAP_DN_RDN_SEP(c) ( (c) == ',' ) 433 #define LDAP_DN_RDN_SEP_V2(c) ( LDAP_DN_RDN_SEP(c) || (c) == ';' ) 434 #define LDAP_DN_OCTOTHORPE(c) ( (c) == '#' ) 435 #define LDAP_DN_QUOTES(c) ( (c) == '\"' ) 436 #define LDAP_DN_ESCAPE(c) ( (c) == '\\' ) 437 #define LDAP_DN_VALUE_END(c) \ 438 ( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) ) 439 440 /* NOTE: according to RFC 4514, '=' can be escaped and treated as special, 441 * i.e. escaped both as "\<hexpair>" and * as "\=", but it is treated as 442 * a regular char, i.e. it can also appear as '='. 443 * 444 * As such, in 2.2 we used to allow reading unescaped '=', but we always 445 * produced escaped '\3D'; this changes since 2.3, if compatibility issues 446 * do not arise 447 */ 448 #define LDAP_DN_NE(c) \ 449 ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) \ 450 || LDAP_DN_QUOTES(c) \ 451 || (c) == '<' || (c) == '>' ) 452 #define LDAP_DN_MAYESCAPE(c) \ 453 ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) \ 454 || LDAP_DN_AVA_EQUALS(c) \ 455 || LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) ) 456 #define LDAP_DN_SHOULDESCAPE(c) ( LDAP_DN_AVA_EQUALS(c) ) 457 458 #define LDAP_DN_NEEDESCAPE(c) \ 459 ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) ) 460 #define LDAP_DN_NEEDESCAPE_LEAD(c) LDAP_DN_MAYESCAPE(c) 461 #define LDAP_DN_NEEDESCAPE_TRAIL(c) \ 462 ( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_NEEDESCAPE(c) ) 463 #define LDAP_DN_WILLESCAPE_CHAR(c) \ 464 ( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) || LDAP_DN_ESCAPE(c) ) 465 #define LDAP_DN_IS_PRETTY(f) ( (f) & LDAP_DN_PRETTY ) 466 #define LDAP_DN_WILLESCAPE_HEX(f, c) \ 467 ( ( !LDAP_DN_IS_PRETTY( f ) ) && LDAP_DN_WILLESCAPE_CHAR(c) ) 468 469 /* LDAPv2 */ 470 #define LDAP_DN_VALUE_END_V2(c) \ 471 ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) ) 472 /* RFC 1779 */ 473 #define LDAP_DN_V2_SPECIAL(c) \ 474 ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_EQUALS(c) \ 475 || LDAP_DN_AVA_SEP(c) || (c) == '<' || (c) == '>' \ 476 || LDAP_DN_OCTOTHORPE(c) ) 477 #define LDAP_DN_V2_PAIR(c) \ 478 ( LDAP_DN_V2_SPECIAL(c) || LDAP_DN_ESCAPE(c) || LDAP_DN_QUOTES(c) ) 479 480 /* 481 * DCE (mostly from Luke Howard and IBM implementation for AIX) 482 * 483 * From: "Application Development Guide - Directory Services" (FIXME: add link?) 484 * Here escapes and valid chars for GDS are considered; as soon as more 485 * specific info is found, the macros will be updated. 486 * 487 * Chars: 'a'-'z', 'A'-'Z', '0'-'9', 488 * '.', ':', ',', ''', '+', '-', '=', '(', ')', '?', '/', ' '. 489 * 490 * Metachars: '/', ',', '=', '\'. 491 * 492 * the '\' is used to escape other metachars. 493 * 494 * Assertion: '=' 495 * RDN separator: '/' 496 * AVA separator: ',' 497 * 498 * Attribute types must start with alphabetic chars and can contain 499 * alphabetic chars and digits (FIXME: no '-'?). OIDs are allowed. 500 */ 501 #define LDAP_DN_RDN_SEP_DCE(c) ( (c) == '/' ) 502 #define LDAP_DN_AVA_SEP_DCE(c) ( (c) == ',' ) 503 #define LDAP_DN_ESCAPE_DCE(c) ( LDAP_DN_ESCAPE(c) ) 504 #define LDAP_DN_VALUE_END_DCE(c) \ 505 ( LDAP_DN_RDN_SEP_DCE(c) || LDAP_DN_AVA_SEP_DCE(c) ) 506 #define LDAP_DN_NEEDESCAPE_DCE(c) \ 507 ( LDAP_DN_VALUE_END_DCE(c) || LDAP_DN_AVA_EQUALS(c) ) 508 509 /* AD Canonical */ 510 #define LDAP_DN_RDN_SEP_AD(c) ( (c) == '/' ) 511 #define LDAP_DN_ESCAPE_AD(c) ( LDAP_DN_ESCAPE(c) ) 512 #define LDAP_DN_AVA_SEP_AD(c) ( (c) == ',' ) /* assume same as DCE */ 513 #define LDAP_DN_VALUE_END_AD(c) \ 514 ( LDAP_DN_RDN_SEP_AD(c) || LDAP_DN_AVA_SEP_AD(c) ) 515 #define LDAP_DN_NEEDESCAPE_AD(c) \ 516 ( LDAP_DN_VALUE_END_AD(c) || LDAP_DN_AVA_EQUALS(c) ) 517 518 /* generics */ 519 #define LDAP_DN_HEXPAIR(s) \ 520 ( LDAP_DN_ASCII_HEXDIGIT((s)[0]) && LDAP_DN_ASCII_HEXDIGIT((s)[1]) ) 521 /* better look at the AttributeDescription? */ 522 523 /* FIXME: no composite rdn or non-"dc" types, right? 524 * (what about "dc" in OID form?) */ 525 /* FIXME: we do not allow binary values in domain, right? */ 526 /* NOTE: use this macro only when ABSOLUTELY SURE rdn IS VALID! */ 527 /* NOTE: don't use strcasecmp() as it is locale specific! */ 528 #define LDAP_DC_ATTR "dc" 529 #define LDAP_DC_ATTRU "DC" 530 #define LDAP_DN_IS_RDN_DC( r ) \ 531 ( (r) && (r)[0] && !(r)[1] \ 532 && ((r)[0]->la_flags & LDAP_AVA_STRING) \ 533 && ((r)[0]->la_attr.bv_len == 2) \ 534 && (((r)[0]->la_attr.bv_val[0] == LDAP_DC_ATTR[0]) \ 535 || ((r)[0]->la_attr.bv_val[0] == LDAP_DC_ATTRU[0])) \ 536 && (((r)[0]->la_attr.bv_val[1] == LDAP_DC_ATTR[1]) \ 537 || ((r)[0]->la_attr.bv_val[1] == LDAP_DC_ATTRU[1]))) 538 539 /* Composite rules */ 540 #define LDAP_DN_ALLOW_ONE_SPACE(f) \ 541 ( LDAP_DN_LDAPV2(f) \ 542 || !( (f) & LDAP_DN_P_NOSPACEAFTERRDN ) ) 543 #define LDAP_DN_ALLOW_SPACES(f) \ 544 ( LDAP_DN_LDAPV2(f) \ 545 || !( (f) & ( LDAP_DN_P_NOLEADTRAILSPACES | LDAP_DN_P_NOSPACEAFTERRDN ) ) ) 546 #define LDAP_DN_LDAP(f) \ 547 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAP ) 548 #define LDAP_DN_LDAPV3(f) \ 549 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV3 ) 550 #define LDAP_DN_LDAPV2(f) \ 551 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV2 ) 552 #define LDAP_DN_DCE(f) \ 553 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_DCE ) 554 #define LDAP_DN_UFN(f) \ 555 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_UFN ) 556 #define LDAP_DN_ADC(f) \ 557 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_AD_CANONICAL ) 558 #define LDAP_DN_FORMAT(f) ( (f) & LDAP_DN_FORMAT_MASK ) 559 560 /* 561 * LDAPAVA helpers (will become part of the API for operations 562 * on structural representations of DNs). 563 */ 564 static LDAPAVA * 565 ldapava_new( const struct berval *attr, const struct berval *val, 566 unsigned flags, void *ctx ) 567 { 568 LDAPAVA *ava; 569 570 assert( attr != NULL ); 571 assert( val != NULL ); 572 573 ava = LDAP_MALLOCX( sizeof( LDAPAVA ) + attr->bv_len + 1, ctx ); 574 575 if ( ava ) { 576 ava->la_attr.bv_len = attr->bv_len; 577 ava->la_attr.bv_val = (char *)(ava+1); 578 AC_MEMCPY( ava->la_attr.bv_val, attr->bv_val, attr->bv_len ); 579 ava->la_attr.bv_val[attr->bv_len] = '\0'; 580 581 ava->la_value = *val; 582 ava->la_flags = flags | LDAP_AVA_FREE_VALUE; 583 584 ava->la_private = NULL; 585 } 586 587 return( ava ); 588 } 589 590 static void 591 ldapava_free( LDAPAVA *ava, void *ctx ) 592 { 593 assert( ava != NULL ); 594 595 #if 0 596 /* ava's private must be freed by caller 597 * (at present let's skip this check because la_private 598 * basically holds static data) */ 599 assert( ava->la_private == NULL ); 600 #endif 601 602 if (ava->la_flags & LDAP_AVA_FREE_VALUE) 603 LDAP_FREEX( ava->la_value.bv_val, ctx ); 604 605 LDAP_FREEX( ava, ctx ); 606 } 607 608 void 609 ldap_rdnfree( LDAPRDN rdn ) 610 { 611 ldap_rdnfree_x( rdn, NULL ); 612 } 613 614 void 615 ldap_rdnfree_x( LDAPRDN rdn, void *ctx ) 616 { 617 int iAVA; 618 619 if ( rdn == NULL ) { 620 return; 621 } 622 623 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { 624 ldapava_free( rdn[ iAVA ], ctx ); 625 } 626 627 LDAP_FREEX( rdn, ctx ); 628 } 629 630 void 631 ldap_dnfree( LDAPDN dn ) 632 { 633 ldap_dnfree_x( dn, NULL ); 634 } 635 636 void 637 ldap_dnfree_x( LDAPDN dn, void *ctx ) 638 { 639 int iRDN; 640 641 if ( dn == NULL ) { 642 return; 643 } 644 645 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) { 646 ldap_rdnfree_x( dn[ iRDN ], ctx ); 647 } 648 649 LDAP_FREEX( dn, ctx ); 650 } 651 652 /* 653 * Converts a string representation of a DN (in LDAPv3, LDAPv2 or DCE) 654 * into a structural representation of the DN, by separating attribute 655 * types and values encoded in the more appropriate form, which is 656 * string or OID for attribute types and binary form of the BER encoded 657 * value or Unicode string. Formats different from LDAPv3 are parsed 658 * according to their own rules and turned into the more appropriate 659 * form according to LDAPv3. 660 * 661 * NOTE: I realize the code is getting spaghettish; it is rather 662 * experimental and will hopefully turn into something more simple 663 * and readable as soon as it works as expected. 664 */ 665 666 /* 667 * Default sizes of AVA and RDN static working arrays; if required 668 * the are dynamically resized. The values can be tuned in case 669 * of special requirements (e.g. very deep DN trees or high number 670 * of AVAs per RDN). 671 */ 672 #define TMP_AVA_SLOTS 8 673 #define TMP_RDN_SLOTS 32 674 675 int 676 ldap_str2dn( LDAP_CONST char *str, LDAPDN *dn, unsigned flags ) 677 { 678 struct berval bv; 679 680 assert( str != NULL ); 681 682 bv.bv_len = strlen( str ); 683 bv.bv_val = (char *) str; 684 685 return ldap_bv2dn_x( &bv, dn, flags, NULL ); 686 } 687 688 int 689 ldap_bv2dn( struct berval *bv, LDAPDN *dn, unsigned flags ) 690 { 691 return ldap_bv2dn_x( bv, dn, flags, NULL ); 692 } 693 694 int 695 ldap_bv2dn_x( struct berval *bvin, LDAPDN *dn, unsigned flags, void *ctx ) 696 { 697 const char *p; 698 int rc = LDAP_DECODING_ERROR; 699 int nrdns = 0; 700 701 LDAPDN newDN = NULL; 702 LDAPRDN newRDN = NULL, tmpDN_[TMP_RDN_SLOTS], *tmpDN = tmpDN_; 703 int num_slots = TMP_RDN_SLOTS; 704 char *str, *end; 705 struct berval bvtmp, *bv = &bvtmp; 706 707 assert( bvin != NULL ); 708 assert( bvin->bv_val != NULL ); 709 assert( dn != NULL ); 710 711 *bv = *bvin; 712 str = bv->bv_val; 713 end = str + bv->bv_len; 714 715 Debug( LDAP_DEBUG_ARGS, "=> ldap_bv2dn(%s,%u)\n", str, flags, 0 ); 716 717 *dn = NULL; 718 719 switch ( LDAP_DN_FORMAT( flags ) ) { 720 case LDAP_DN_FORMAT_LDAP: 721 case LDAP_DN_FORMAT_LDAPV3: 722 case LDAP_DN_FORMAT_DCE: 723 break; 724 725 /* allow DN enclosed in brackets */ 726 case LDAP_DN_FORMAT_LDAPV2: 727 if ( str[0] == '<' ) { 728 if ( bv->bv_len < 2 || end[ -1 ] != '>' ) { 729 rc = LDAP_DECODING_ERROR; 730 goto parsing_error; 731 } 732 bv->bv_val++; 733 bv->bv_len -= 2; 734 str++; 735 end--; 736 } 737 break; 738 739 /* unsupported in str2dn */ 740 case LDAP_DN_FORMAT_UFN: 741 case LDAP_DN_FORMAT_AD_CANONICAL: 742 return LDAP_PARAM_ERROR; 743 744 case LDAP_DN_FORMAT_LBER: 745 default: 746 return LDAP_PARAM_ERROR; 747 } 748 749 if ( bv->bv_len == 0 ) { 750 return LDAP_SUCCESS; 751 } 752 753 if( memchr( bv->bv_val, '\0', bv->bv_len ) != NULL ) { 754 /* value must have embedded NULs */ 755 return LDAP_DECODING_ERROR; 756 } 757 758 p = str; 759 if ( LDAP_DN_DCE( flags ) ) { 760 761 /* 762 * (from Luke Howard: thnx) A RDN separator is required 763 * at the beginning of an (absolute) DN. 764 */ 765 if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) { 766 goto parsing_error; 767 } 768 p++; 769 770 /* 771 * actually we do not want to accept by default the DCE form, 772 * we do not want to auto-detect it 773 */ 774 #if 0 775 } else if ( LDAP_DN_LDAP( flags ) ) { 776 /* 777 * if dn starts with '/' let's make it a DCE dn 778 */ 779 if ( LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) { 780 flags |= LDAP_DN_FORMAT_DCE; 781 p++; 782 } 783 #endif 784 } 785 786 for ( ; p < end; p++ ) { 787 int err; 788 struct berval tmpbv; 789 tmpbv.bv_len = bv->bv_len - ( p - str ); 790 tmpbv.bv_val = (char *)p; 791 792 err = ldap_bv2rdn_x( &tmpbv, &newRDN, (char **) &p, flags,ctx); 793 if ( err != LDAP_SUCCESS ) { 794 goto parsing_error; 795 } 796 797 /* 798 * We expect a rdn separator 799 */ 800 if ( p < end && p[ 0 ] ) { 801 switch ( LDAP_DN_FORMAT( flags ) ) { 802 case LDAP_DN_FORMAT_LDAPV3: 803 if ( !LDAP_DN_RDN_SEP( p[ 0 ] ) ) { 804 rc = LDAP_DECODING_ERROR; 805 goto parsing_error; 806 } 807 break; 808 809 case LDAP_DN_FORMAT_LDAP: 810 case LDAP_DN_FORMAT_LDAPV2: 811 if ( !LDAP_DN_RDN_SEP_V2( p[ 0 ] ) ) { 812 rc = LDAP_DECODING_ERROR; 813 goto parsing_error; 814 } 815 break; 816 817 case LDAP_DN_FORMAT_DCE: 818 if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) { 819 rc = LDAP_DECODING_ERROR; 820 goto parsing_error; 821 } 822 break; 823 } 824 } 825 826 827 tmpDN[nrdns++] = newRDN; 828 newRDN = NULL; 829 830 /* 831 * make the static RDN array dynamically rescalable 832 */ 833 if ( nrdns == num_slots ) { 834 LDAPRDN *tmp; 835 836 if ( tmpDN == tmpDN_ ) { 837 tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPRDN * ), ctx ); 838 if ( tmp == NULL ) { 839 rc = LDAP_NO_MEMORY; 840 goto parsing_error; 841 } 842 AC_MEMCPY( tmp, tmpDN, num_slots * sizeof( LDAPRDN * ) ); 843 844 } else { 845 tmp = LDAP_REALLOCX( tmpDN, num_slots * 2 * sizeof( LDAPRDN * ), ctx ); 846 if ( tmp == NULL ) { 847 rc = LDAP_NO_MEMORY; 848 goto parsing_error; 849 } 850 } 851 852 tmpDN = tmp; 853 num_slots *= 2; 854 } 855 856 if ( p >= end || p[ 0 ] == '\0' ) { 857 /* 858 * the DN is over, phew 859 */ 860 newDN = (LDAPDN)LDAP_MALLOCX( sizeof(LDAPRDN *) * (nrdns+1), ctx ); 861 if ( newDN == NULL ) { 862 rc = LDAP_NO_MEMORY; 863 goto parsing_error; 864 } else { 865 int i; 866 867 if ( LDAP_DN_DCE( flags ) ) { 868 /* add in reversed order */ 869 for ( i=0; i<nrdns; i++ ) 870 newDN[i] = tmpDN[nrdns-1-i]; 871 } else { 872 for ( i=0; i<nrdns; i++ ) 873 newDN[i] = tmpDN[i]; 874 } 875 newDN[nrdns] = NULL; 876 rc = LDAP_SUCCESS; 877 } 878 goto return_result; 879 } 880 } 881 882 parsing_error:; 883 if ( newRDN ) { 884 ldap_rdnfree_x( newRDN, ctx ); 885 } 886 887 for ( nrdns-- ;nrdns >= 0; nrdns-- ) { 888 ldap_rdnfree_x( tmpDN[nrdns], ctx ); 889 } 890 891 return_result:; 892 893 if ( tmpDN != tmpDN_ ) { 894 LDAP_FREEX( tmpDN, ctx ); 895 } 896 897 Debug( LDAP_DEBUG_ARGS, "<= ldap_bv2dn(%s)=%d %s\n", str, rc, 898 rc ? ldap_err2string( rc ) : "" ); 899 *dn = newDN; 900 901 return( rc ); 902 } 903 904 /* 905 * ldap_str2rdn 906 * 907 * Parses a relative DN according to flags up to a rdn separator 908 * or to the end of str. 909 * Returns the rdn and a pointer to the string continuation, which 910 * corresponds to the rdn separator or to '\0' in case the string is over. 911 */ 912 int 913 ldap_str2rdn( LDAP_CONST char *str, LDAPRDN *rdn, 914 char **n_in, unsigned flags ) 915 { 916 struct berval bv; 917 918 assert( str != NULL ); 919 assert( str[ 0 ] != '\0' ); /* FIXME: is this required? */ 920 921 bv.bv_len = strlen( str ); 922 bv.bv_val = (char *) str; 923 924 return ldap_bv2rdn_x( &bv, rdn, n_in, flags, NULL ); 925 } 926 927 int 928 ldap_bv2rdn( struct berval *bv, LDAPRDN *rdn, 929 char **n_in, unsigned flags ) 930 { 931 return ldap_bv2rdn_x( bv, rdn, n_in, flags, NULL ); 932 } 933 934 int 935 ldap_bv2rdn_x( struct berval *bv, LDAPRDN *rdn, 936 char **n_in, unsigned flags, void *ctx ) 937 { 938 const char **n = (const char **) n_in; 939 const char *p; 940 int navas = 0; 941 int state = B4AVA; 942 int rc = LDAP_DECODING_ERROR; 943 int attrTypeEncoding = LDAP_AVA_STRING, 944 attrValueEncoding = LDAP_AVA_STRING; 945 946 struct berval attrType = BER_BVNULL; 947 struct berval attrValue = BER_BVNULL; 948 949 LDAPRDN newRDN = NULL; 950 LDAPAVA *tmpRDN_[TMP_AVA_SLOTS], **tmpRDN = tmpRDN_; 951 int num_slots = TMP_AVA_SLOTS; 952 953 char *str; 954 ber_len_t stoplen; 955 956 assert( bv != NULL ); 957 assert( bv->bv_len != 0 ); 958 assert( bv->bv_val != NULL ); 959 assert( rdn || flags & LDAP_DN_SKIP ); 960 assert( n != NULL ); 961 962 str = bv->bv_val; 963 stoplen = bv->bv_len; 964 965 if ( rdn ) { 966 *rdn = NULL; 967 } 968 *n = NULL; 969 970 switch ( LDAP_DN_FORMAT( flags ) ) { 971 case LDAP_DN_FORMAT_LDAP: 972 case LDAP_DN_FORMAT_LDAPV3: 973 case LDAP_DN_FORMAT_LDAPV2: 974 case LDAP_DN_FORMAT_DCE: 975 break; 976 977 /* unsupported in str2dn */ 978 case LDAP_DN_FORMAT_UFN: 979 case LDAP_DN_FORMAT_AD_CANONICAL: 980 return LDAP_PARAM_ERROR; 981 982 case LDAP_DN_FORMAT_LBER: 983 default: 984 return LDAP_PARAM_ERROR; 985 } 986 987 if ( bv->bv_len == 0 ) { 988 return LDAP_SUCCESS; 989 990 } 991 992 if( memchr( bv->bv_val, '\0', bv->bv_len ) != NULL ) { 993 /* value must have embedded NULs */ 994 return LDAP_DECODING_ERROR; 995 } 996 997 p = str; 998 for ( ; p[ 0 ] || state == GOTAVA; ) { 999 1000 /* 1001 * The parser in principle advances one token a time, 1002 * or toggles state if preferable. 1003 */ 1004 switch (state) { 1005 1006 /* 1007 * an AttributeType can be encoded as: 1008 * - its string representation; in detail, implementations 1009 * MUST recognize AttributeType string type names listed 1010 * in Section 3 of RFC 4514, and MAY recognize other names. 1011 * - its numeric OID (a dotted decimal string) 1012 */ 1013 case B4AVA: 1014 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { 1015 if ( !LDAP_DN_ALLOW_ONE_SPACE( flags ) ) { 1016 /* error */ 1017 goto parsing_error; 1018 } 1019 p++; 1020 } 1021 1022 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { 1023 if ( !LDAP_DN_ALLOW_SPACES( flags ) ) { 1024 /* error */ 1025 goto parsing_error; 1026 } 1027 1028 /* whitespace is allowed (and trimmed) */ 1029 p++; 1030 while ( p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { 1031 p++; 1032 } 1033 1034 if ( !p[ 0 ] ) { 1035 /* error: we expected an AVA */ 1036 goto parsing_error; 1037 } 1038 } 1039 1040 /* oid */ 1041 if ( LDAP_DN_OID_LEADCHAR( p[ 0 ] ) ) { 1042 state = B4OIDATTRTYPE; 1043 break; 1044 } 1045 1046 /* else must be alpha */ 1047 if ( !LDAP_DN_DESC_LEADCHAR( p[ 0 ] ) ) { 1048 goto parsing_error; 1049 } 1050 1051 /* LDAPv2 "oid." prefix */ 1052 if ( LDAP_DN_LDAPV2( flags ) ) { 1053 /* 1054 * to be overly pedantic, we only accept 1055 * "OID." or "oid." 1056 */ 1057 if ( flags & LDAP_DN_PEDANTIC ) { 1058 if ( !strncmp( p, "OID.", 4 ) 1059 || !strncmp( p, "oid.", 4 ) ) { 1060 p += 4; 1061 state = B4OIDATTRTYPE; 1062 break; 1063 } 1064 } else { 1065 if ( !strncasecmp( p, "oid.", 4 ) ) { 1066 p += 4; 1067 state = B4OIDATTRTYPE; 1068 break; 1069 } 1070 } 1071 } 1072 1073 state = B4STRINGATTRTYPE; 1074 break; 1075 1076 case B4OIDATTRTYPE: { 1077 int err = LDAP_SUCCESS; 1078 1079 attrType.bv_val = ldap_int_parse_numericoid( &p, &err, 1080 LDAP_SCHEMA_SKIP); 1081 1082 if ( err != LDAP_SUCCESS ) { 1083 goto parsing_error; 1084 } 1085 attrType.bv_len = p - attrType.bv_val; 1086 1087 attrTypeEncoding = LDAP_AVA_BINARY; 1088 1089 state = B4AVAEQUALS; 1090 break; 1091 } 1092 1093 case B4STRINGATTRTYPE: { 1094 const char *startPos, *endPos = NULL; 1095 ber_len_t len; 1096 1097 /* 1098 * the starting char has been found to be 1099 * a LDAP_DN_DESC_LEADCHAR so we don't re-check it 1100 * FIXME: DCE attr types seem to have a more 1101 * restrictive syntax (no '-' ...) 1102 */ 1103 for ( startPos = p++; p[ 0 ]; p++ ) { 1104 if ( LDAP_DN_DESC_CHAR( p[ 0 ] ) ) { 1105 continue; 1106 } 1107 1108 if ( LDAP_DN_LANG_SEP( p[ 0 ] ) ) { 1109 1110 /* 1111 * RFC 4514 explicitly does not allow attribute 1112 * description options, such as language tags. 1113 */ 1114 if ( flags & LDAP_DN_PEDANTIC ) { 1115 goto parsing_error; 1116 } 1117 1118 /* 1119 * we trim ';' and following lang 1120 * and so from attribute types 1121 */ 1122 endPos = p; 1123 for ( ; LDAP_DN_ATTRDESC_CHAR( p[ 0 ] ) 1124 || LDAP_DN_LANG_SEP( p[ 0 ] ); p++ ) { 1125 /* no op */ ; 1126 } 1127 break; 1128 } 1129 break; 1130 } 1131 1132 len = ( endPos ? endPos : p ) - startPos; 1133 if ( len == 0 ) { 1134 goto parsing_error; 1135 } 1136 1137 attrTypeEncoding = LDAP_AVA_STRING; 1138 1139 /* 1140 * here we need to decide whether to use it as is 1141 * or turn it in OID form; as a consequence, we 1142 * need to decide whether to binary encode the value 1143 */ 1144 1145 state = B4AVAEQUALS; 1146 1147 if ( flags & LDAP_DN_SKIP ) { 1148 break; 1149 } 1150 1151 attrType.bv_val = (char *)startPos; 1152 attrType.bv_len = len; 1153 1154 break; 1155 } 1156 1157 case B4AVAEQUALS: 1158 /* spaces may not be allowed */ 1159 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { 1160 if ( !LDAP_DN_ALLOW_SPACES( flags ) ) { 1161 goto parsing_error; 1162 } 1163 1164 /* trim spaces */ 1165 for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) { 1166 /* no op */ 1167 } 1168 } 1169 1170 /* need equal sign */ 1171 if ( !LDAP_DN_AVA_EQUALS( p[ 0 ] ) ) { 1172 goto parsing_error; 1173 } 1174 p++; 1175 1176 /* spaces may not be allowed */ 1177 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { 1178 if ( !LDAP_DN_ALLOW_SPACES( flags ) ) { 1179 goto parsing_error; 1180 } 1181 1182 /* trim spaces */ 1183 for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) { 1184 /* no op */ 1185 } 1186 } 1187 1188 /* 1189 * octothorpe means a BER encoded value will follow 1190 * FIXME: I don't think DCE will allow it 1191 */ 1192 if ( LDAP_DN_OCTOTHORPE( p[ 0 ] ) ) { 1193 p++; 1194 attrValueEncoding = LDAP_AVA_BINARY; 1195 state = B4BINARYVALUE; 1196 break; 1197 } 1198 1199 /* STRING value expected */ 1200 1201 /* 1202 * if we're pedantic, an attribute type in OID form 1203 * SHOULD imply a BER encoded attribute value; we 1204 * should at least issue a warning 1205 */ 1206 if ( ( flags & LDAP_DN_PEDANTIC ) 1207 && ( attrTypeEncoding == LDAP_AVA_BINARY ) ) { 1208 /* OID attrType SHOULD use binary encoding */ 1209 goto parsing_error; 1210 } 1211 1212 attrValueEncoding = LDAP_AVA_STRING; 1213 1214 /* 1215 * LDAPv2 allows the attribute value to be quoted; 1216 * also, IA5 values are expected, in principle 1217 */ 1218 if ( LDAP_DN_LDAPV2( flags ) || LDAP_DN_LDAP( flags ) ) { 1219 if ( LDAP_DN_QUOTES( p[ 0 ] ) ) { 1220 p++; 1221 state = B4IA5VALUEQUOTED; 1222 break; 1223 } 1224 1225 if ( LDAP_DN_LDAPV2( flags ) ) { 1226 state = B4IA5VALUE; 1227 break; 1228 } 1229 } 1230 1231 /* 1232 * here STRING means RFC 4514 string 1233 * FIXME: what about DCE strings? 1234 */ 1235 if ( !p[ 0 ] ) { 1236 /* empty value */ 1237 state = GOTAVA; 1238 } else { 1239 state = B4STRINGVALUE; 1240 } 1241 break; 1242 1243 case B4BINARYVALUE: 1244 if ( hexstr2binval( p, &attrValue, &p, flags, ctx ) ) { 1245 goto parsing_error; 1246 } 1247 1248 state = GOTAVA; 1249 break; 1250 1251 case B4STRINGVALUE: 1252 switch ( LDAP_DN_FORMAT( flags ) ) { 1253 case LDAP_DN_FORMAT_LDAP: 1254 case LDAP_DN_FORMAT_LDAPV3: 1255 if ( str2strval( p, stoplen - ( p - str ), 1256 &attrValue, &p, flags, 1257 &attrValueEncoding, ctx ) ) { 1258 goto parsing_error; 1259 } 1260 break; 1261 1262 case LDAP_DN_FORMAT_DCE: 1263 if ( DCE2strval( p, &attrValue, &p, flags, ctx ) ) { 1264 goto parsing_error; 1265 } 1266 break; 1267 1268 default: 1269 assert( 0 ); 1270 } 1271 1272 state = GOTAVA; 1273 break; 1274 1275 case B4IA5VALUE: 1276 if ( IA52strval( p, &attrValue, &p, flags, ctx ) ) { 1277 goto parsing_error; 1278 } 1279 1280 state = GOTAVA; 1281 break; 1282 1283 case B4IA5VALUEQUOTED: 1284 1285 /* lead quote already stripped */ 1286 if ( quotedIA52strval( p, &attrValue, 1287 &p, flags, ctx ) ) { 1288 goto parsing_error; 1289 } 1290 1291 state = GOTAVA; 1292 break; 1293 1294 case GOTAVA: { 1295 int rdnsep = 0; 1296 1297 if ( !( flags & LDAP_DN_SKIP ) ) { 1298 LDAPAVA *ava; 1299 1300 /* 1301 * we accept empty values 1302 */ 1303 ava = ldapava_new( &attrType, &attrValue, 1304 attrValueEncoding, ctx ); 1305 if ( ava == NULL ) { 1306 rc = LDAP_NO_MEMORY; 1307 goto parsing_error; 1308 } 1309 tmpRDN[navas++] = ava; 1310 1311 attrValue.bv_val = NULL; 1312 attrValue.bv_len = 0; 1313 1314 /* 1315 * prepare room for new AVAs if needed 1316 */ 1317 if (navas == num_slots) { 1318 LDAPAVA **tmp; 1319 1320 if ( tmpRDN == tmpRDN_ ) { 1321 tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPAVA * ), ctx ); 1322 if ( tmp == NULL ) { 1323 rc = LDAP_NO_MEMORY; 1324 goto parsing_error; 1325 } 1326 AC_MEMCPY( tmp, tmpRDN, num_slots * sizeof( LDAPAVA * ) ); 1327 1328 } else { 1329 tmp = LDAP_REALLOCX( tmpRDN, num_slots * 2 * sizeof( LDAPAVA * ), ctx ); 1330 if ( tmp == NULL ) { 1331 rc = LDAP_NO_MEMORY; 1332 goto parsing_error; 1333 } 1334 } 1335 1336 tmpRDN = tmp; 1337 num_slots *= 2; 1338 } 1339 } 1340 1341 /* 1342 * if we got an AVA separator ('+', or ',' for DCE ) 1343 * we expect a new AVA for this RDN; otherwise 1344 * we add the RDN to the DN 1345 */ 1346 switch ( LDAP_DN_FORMAT( flags ) ) { 1347 case LDAP_DN_FORMAT_LDAP: 1348 case LDAP_DN_FORMAT_LDAPV3: 1349 case LDAP_DN_FORMAT_LDAPV2: 1350 if ( !LDAP_DN_AVA_SEP( p[ 0 ] ) ) { 1351 rdnsep = 1; 1352 } 1353 break; 1354 1355 case LDAP_DN_FORMAT_DCE: 1356 if ( !LDAP_DN_AVA_SEP_DCE( p[ 0 ] ) ) { 1357 rdnsep = 1; 1358 } 1359 break; 1360 } 1361 1362 if ( rdnsep ) { 1363 /* 1364 * the RDN is over, phew 1365 */ 1366 *n = p; 1367 if ( !( flags & LDAP_DN_SKIP ) ) { 1368 newRDN = (LDAPRDN)LDAP_MALLOCX( 1369 sizeof(LDAPAVA) * (navas+1), ctx ); 1370 if ( newRDN == NULL ) { 1371 rc = LDAP_NO_MEMORY; 1372 goto parsing_error; 1373 } else { 1374 AC_MEMCPY( newRDN, tmpRDN, sizeof(LDAPAVA *) * navas); 1375 newRDN[navas] = NULL; 1376 } 1377 1378 } 1379 rc = LDAP_SUCCESS; 1380 goto return_result; 1381 } 1382 1383 /* they should have been used in an AVA */ 1384 attrType.bv_val = NULL; 1385 attrValue.bv_val = NULL; 1386 1387 p++; 1388 state = B4AVA; 1389 break; 1390 } 1391 1392 default: 1393 assert( 0 ); 1394 goto parsing_error; 1395 } 1396 } 1397 *n = p; 1398 1399 parsing_error:; 1400 /* They are set to NULL after they're used in an AVA */ 1401 1402 if ( attrValue.bv_val ) { 1403 LDAP_FREEX( attrValue.bv_val, ctx ); 1404 } 1405 1406 for ( navas-- ; navas >= 0; navas-- ) { 1407 ldapava_free( tmpRDN[navas], ctx ); 1408 } 1409 1410 return_result:; 1411 1412 if ( tmpRDN != tmpRDN_ ) { 1413 LDAP_FREEX( tmpRDN, ctx ); 1414 } 1415 1416 if ( rdn ) { 1417 *rdn = newRDN; 1418 } 1419 1420 return( rc ); 1421 } 1422 1423 /* 1424 * reads in a UTF-8 string value, unescaping stuff: 1425 * '\' + LDAP_DN_NEEDESCAPE(c) -> 'c' 1426 * '\' + HEXPAIR(p) -> unhex(p) 1427 */ 1428 static int 1429 str2strval( const char *str, ber_len_t stoplen, struct berval *val, const char **next, unsigned flags, int *retFlags, void *ctx ) 1430 { 1431 const char *p, *end, *startPos, *endPos = NULL; 1432 ber_len_t len, escapes; 1433 1434 assert( str != NULL ); 1435 assert( val != NULL ); 1436 assert( next != NULL ); 1437 1438 *next = NULL; 1439 end = str + stoplen; 1440 for ( startPos = p = str, escapes = 0; p < end; p++ ) { 1441 if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) { 1442 p++; 1443 if ( p[ 0 ] == '\0' ) { 1444 return( 1 ); 1445 } 1446 if ( LDAP_DN_MAYESCAPE( p[ 0 ] ) ) { 1447 escapes++; 1448 continue; 1449 } 1450 1451 if ( LDAP_DN_HEXPAIR( p ) ) { 1452 char c; 1453 1454 hexstr2bin( p, &c ); 1455 escapes += 2; 1456 1457 if ( !LDAP_DN_ASCII_PRINTABLE( c ) ) { 1458 1459 /* 1460 * we assume the string is UTF-8 1461 */ 1462 *retFlags = LDAP_AVA_NONPRINTABLE; 1463 } 1464 p++; 1465 1466 continue; 1467 } 1468 1469 if ( LDAP_DN_PEDANTIC & flags ) { 1470 return( 1 ); 1471 } 1472 /* 1473 * we do not allow escaping 1474 * of chars that don't need 1475 * to and do not belong to 1476 * HEXDIGITS 1477 */ 1478 return( 1 ); 1479 1480 } else if ( !LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) { 1481 if ( p[ 0 ] == '\0' ) { 1482 return( 1 ); 1483 } 1484 *retFlags = LDAP_AVA_NONPRINTABLE; 1485 1486 } else if ( ( LDAP_DN_LDAP( flags ) && LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) 1487 || ( LDAP_DN_LDAPV3( flags ) && LDAP_DN_VALUE_END( p[ 0 ] ) ) ) { 1488 break; 1489 1490 } else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) { 1491 /* 1492 * FIXME: maybe we can add 1493 * escapes if not pedantic? 1494 */ 1495 return( 1 ); 1496 } 1497 } 1498 1499 /* 1500 * we do allow unescaped spaces at the end 1501 * of the value only in non-pedantic mode 1502 */ 1503 if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) && 1504 !LDAP_DN_ESCAPE( p[ -2 ] ) ) { 1505 if ( flags & LDAP_DN_PEDANTIC ) { 1506 return( 1 ); 1507 } 1508 1509 /* strip trailing (unescaped) spaces */ 1510 for ( endPos = p - 1; 1511 endPos > startPos + 1 && 1512 LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) && 1513 !LDAP_DN_ESCAPE( endPos[ -2 ] ); 1514 endPos-- ) { 1515 /* no op */ 1516 } 1517 } 1518 1519 *next = p; 1520 if ( flags & LDAP_DN_SKIP ) { 1521 return( 0 ); 1522 } 1523 1524 /* 1525 * FIXME: test memory? 1526 */ 1527 len = ( endPos ? endPos : p ) - startPos - escapes; 1528 val->bv_len = len; 1529 1530 if ( escapes == 0 ) { 1531 if ( *retFlags & LDAP_AVA_NONPRINTABLE ) { 1532 val->bv_val = LDAP_MALLOCX( len + 1, ctx ); 1533 AC_MEMCPY( val->bv_val, startPos, len ); 1534 val->bv_val[ len ] = '\0'; 1535 } else { 1536 val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); 1537 } 1538 1539 } else { 1540 ber_len_t s, d; 1541 1542 val->bv_val = LDAP_MALLOCX( len + 1, ctx ); 1543 for ( s = 0, d = 0; d < len; ) { 1544 if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) { 1545 s++; 1546 if ( LDAP_DN_MAYESCAPE( startPos[ s ] ) ) { 1547 val->bv_val[ d++ ] = 1548 startPos[ s++ ]; 1549 1550 } else if ( LDAP_DN_HEXPAIR( &startPos[ s ] ) ) { 1551 char c; 1552 1553 hexstr2bin( &startPos[ s ], &c ); 1554 val->bv_val[ d++ ] = c; 1555 s += 2; 1556 1557 } else { 1558 /* we should never get here */ 1559 assert( 0 ); 1560 } 1561 1562 } else { 1563 val->bv_val[ d++ ] = startPos[ s++ ]; 1564 } 1565 } 1566 1567 val->bv_val[ d ] = '\0'; 1568 assert( d == len ); 1569 } 1570 1571 return( 0 ); 1572 } 1573 1574 static int 1575 DCE2strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) 1576 { 1577 const char *p, *startPos, *endPos = NULL; 1578 ber_len_t len, escapes; 1579 1580 assert( str != NULL ); 1581 assert( val != NULL ); 1582 assert( next != NULL ); 1583 1584 *next = NULL; 1585 1586 for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) { 1587 if ( LDAP_DN_ESCAPE_DCE( p[ 0 ] ) ) { 1588 p++; 1589 if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) { 1590 escapes++; 1591 1592 } else { 1593 return( 1 ); 1594 } 1595 1596 } else if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) { 1597 break; 1598 } 1599 1600 /* 1601 * FIXME: can we accept anything else? I guess we need 1602 * to stop if a value is not legal 1603 */ 1604 } 1605 1606 /* 1607 * (unescaped) trailing spaces are trimmed must be silently ignored; 1608 * so we eat them 1609 */ 1610 if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) && 1611 !LDAP_DN_ESCAPE( p[ -2 ] ) ) { 1612 if ( flags & LDAP_DN_PEDANTIC ) { 1613 return( 1 ); 1614 } 1615 1616 /* strip trailing (unescaped) spaces */ 1617 for ( endPos = p - 1; 1618 endPos > startPos + 1 && 1619 LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) && 1620 !LDAP_DN_ESCAPE( endPos[ -2 ] ); 1621 endPos-- ) { 1622 /* no op */ 1623 } 1624 } 1625 1626 *next = p; 1627 if ( flags & LDAP_DN_SKIP ) { 1628 return( 0 ); 1629 } 1630 1631 len = ( endPos ? endPos : p ) - startPos - escapes; 1632 val->bv_len = len; 1633 if ( escapes == 0 ){ 1634 val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); 1635 1636 } else { 1637 ber_len_t s, d; 1638 1639 val->bv_val = LDAP_MALLOCX( len + 1, ctx ); 1640 for ( s = 0, d = 0; d < len; ) { 1641 /* 1642 * This point is reached only if escapes 1643 * are properly used, so all we need to 1644 * do is eat them 1645 */ 1646 if ( LDAP_DN_ESCAPE_DCE( startPos[ s ] ) ) { 1647 s++; 1648 1649 } 1650 val->bv_val[ d++ ] = startPos[ s++ ]; 1651 } 1652 val->bv_val[ d ] = '\0'; 1653 assert( strlen( val->bv_val ) == len ); 1654 } 1655 1656 return( 0 ); 1657 } 1658 1659 static int 1660 IA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) 1661 { 1662 const char *p, *startPos, *endPos = NULL; 1663 ber_len_t len, escapes; 1664 1665 assert( str != NULL ); 1666 assert( val != NULL ); 1667 assert( next != NULL ); 1668 1669 *next = NULL; 1670 1671 /* 1672 * LDAPv2 (RFC 1779) 1673 */ 1674 1675 for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) { 1676 if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) { 1677 p++; 1678 if ( p[ 0 ] == '\0' ) { 1679 return( 1 ); 1680 } 1681 1682 if ( !LDAP_DN_NEEDESCAPE( p[ 0 ] ) 1683 && ( LDAP_DN_PEDANTIC & flags ) ) { 1684 return( 1 ); 1685 } 1686 escapes++; 1687 1688 } else if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) { 1689 break; 1690 } 1691 1692 /* 1693 * FIXME: can we accept anything else? I guess we need 1694 * to stop if a value is not legal 1695 */ 1696 } 1697 1698 /* strip trailing (unescaped) spaces */ 1699 for ( endPos = p; 1700 endPos > startPos + 1 && 1701 LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) && 1702 !LDAP_DN_ESCAPE( endPos[ -2 ] ); 1703 endPos-- ) { 1704 /* no op */ 1705 } 1706 1707 *next = p; 1708 if ( flags & LDAP_DN_SKIP ) { 1709 return( 0 ); 1710 } 1711 1712 len = ( endPos ? endPos : p ) - startPos - escapes; 1713 val->bv_len = len; 1714 if ( escapes == 0 ) { 1715 val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); 1716 1717 } else { 1718 ber_len_t s, d; 1719 1720 val->bv_val = LDAP_MALLOCX( len + 1, ctx ); 1721 for ( s = 0, d = 0; d < len; ) { 1722 if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) { 1723 s++; 1724 } 1725 val->bv_val[ d++ ] = startPos[ s++ ]; 1726 } 1727 val->bv_val[ d ] = '\0'; 1728 assert( strlen( val->bv_val ) == len ); 1729 } 1730 1731 return( 0 ); 1732 } 1733 1734 static int 1735 quotedIA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) 1736 { 1737 const char *p, *startPos, *endPos = NULL; 1738 ber_len_t len; 1739 unsigned escapes = 0; 1740 1741 assert( str != NULL ); 1742 assert( val != NULL ); 1743 assert( next != NULL ); 1744 1745 *next = NULL; 1746 1747 /* initial quote already eaten */ 1748 for ( startPos = p = str; p[ 0 ]; p++ ) { 1749 /* 1750 * According to RFC 1779, the quoted value can 1751 * contain escaped as well as unescaped special values; 1752 * as a consequence we tolerate escaped values 1753 * (e.g. '"\,"' -> '\,') and escape unescaped specials 1754 * (e.g. '","' -> '\,'). 1755 */ 1756 if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) { 1757 if ( p[ 1 ] == '\0' ) { 1758 return( 1 ); 1759 } 1760 p++; 1761 1762 if ( !LDAP_DN_V2_PAIR( p[ 0 ] ) 1763 && ( LDAP_DN_PEDANTIC & flags ) ) { 1764 /* 1765 * do we allow to escape normal chars? 1766 * LDAPv2 does not allow any mechanism 1767 * for escaping chars with '\' and hex 1768 * pair 1769 */ 1770 return( 1 ); 1771 } 1772 escapes++; 1773 1774 } else if ( LDAP_DN_QUOTES( p[ 0 ] ) ) { 1775 endPos = p; 1776 /* eat closing quotes */ 1777 p++; 1778 break; 1779 } 1780 1781 /* 1782 * FIXME: can we accept anything else? I guess we need 1783 * to stop if a value is not legal 1784 */ 1785 } 1786 1787 if ( endPos == NULL ) { 1788 return( 1 ); 1789 } 1790 1791 /* Strip trailing (unescaped) spaces */ 1792 for ( ; p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) { 1793 /* no op */ 1794 } 1795 1796 *next = p; 1797 if ( flags & LDAP_DN_SKIP ) { 1798 return( 0 ); 1799 } 1800 1801 len = endPos - startPos - escapes; 1802 assert( endPos >= startPos + escapes ); 1803 val->bv_len = len; 1804 if ( escapes == 0 ) { 1805 val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); 1806 1807 } else { 1808 ber_len_t s, d; 1809 1810 val->bv_val = LDAP_MALLOCX( len + 1, ctx ); 1811 val->bv_len = len; 1812 1813 for ( s = d = 0; d < len; ) { 1814 if ( LDAP_DN_ESCAPE( str[ s ] ) ) { 1815 s++; 1816 } 1817 val->bv_val[ d++ ] = str[ s++ ]; 1818 } 1819 val->bv_val[ d ] = '\0'; 1820 assert( strlen( val->bv_val ) == len ); 1821 } 1822 1823 return( 0 ); 1824 } 1825 1826 static int 1827 hexstr2bin( const char *str, char *c ) 1828 { 1829 char c1, c2; 1830 1831 assert( str != NULL ); 1832 assert( c != NULL ); 1833 1834 c1 = str[ 0 ]; 1835 c2 = str[ 1 ]; 1836 1837 if ( LDAP_DN_ASCII_DIGIT( c1 ) ) { 1838 *c = c1 - '0'; 1839 1840 } else { 1841 if ( LDAP_DN_ASCII_UCASE_HEXALPHA( c1 ) ) { 1842 *c = c1 - 'A' + 10; 1843 } else { 1844 assert( LDAP_DN_ASCII_LCASE_HEXALPHA( c1 ) ); 1845 *c = c1 - 'a' + 10; 1846 } 1847 } 1848 1849 *c <<= 4; 1850 1851 if ( LDAP_DN_ASCII_DIGIT( c2 ) ) { 1852 *c += c2 - '0'; 1853 1854 } else { 1855 if ( LDAP_DN_ASCII_UCASE_HEXALPHA( c2 ) ) { 1856 *c += c2 - 'A' + 10; 1857 } else { 1858 assert( LDAP_DN_ASCII_LCASE_HEXALPHA( c2 ) ); 1859 *c += c2 - 'a' + 10; 1860 } 1861 } 1862 1863 return( 0 ); 1864 } 1865 1866 static int 1867 hexstr2binval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) 1868 { 1869 const char *p, *startPos, *endPos = NULL; 1870 ber_len_t len; 1871 ber_len_t s, d; 1872 1873 assert( str != NULL ); 1874 assert( val != NULL ); 1875 assert( next != NULL ); 1876 1877 *next = NULL; 1878 1879 for ( startPos = p = str; p[ 0 ]; p += 2 ) { 1880 switch ( LDAP_DN_FORMAT( flags ) ) { 1881 case LDAP_DN_FORMAT_LDAPV3: 1882 if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) { 1883 goto end_of_value; 1884 } 1885 break; 1886 1887 case LDAP_DN_FORMAT_LDAP: 1888 case LDAP_DN_FORMAT_LDAPV2: 1889 if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) { 1890 goto end_of_value; 1891 } 1892 break; 1893 1894 case LDAP_DN_FORMAT_DCE: 1895 if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) { 1896 goto end_of_value; 1897 } 1898 break; 1899 } 1900 1901 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { 1902 if ( flags & LDAP_DN_PEDANTIC ) { 1903 return( 1 ); 1904 } 1905 endPos = p; 1906 1907 for ( ; p[ 0 ]; p++ ) { 1908 switch ( LDAP_DN_FORMAT( flags ) ) { 1909 case LDAP_DN_FORMAT_LDAPV3: 1910 if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) { 1911 goto end_of_value; 1912 } 1913 break; 1914 1915 case LDAP_DN_FORMAT_LDAP: 1916 case LDAP_DN_FORMAT_LDAPV2: 1917 if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) { 1918 goto end_of_value; 1919 } 1920 break; 1921 1922 case LDAP_DN_FORMAT_DCE: 1923 if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) { 1924 goto end_of_value; 1925 } 1926 break; 1927 } 1928 } 1929 break; 1930 } 1931 1932 if ( !LDAP_DN_HEXPAIR( p ) ) { 1933 return( 1 ); 1934 } 1935 } 1936 1937 end_of_value:; 1938 1939 *next = p; 1940 if ( flags & LDAP_DN_SKIP ) { 1941 return( 0 ); 1942 } 1943 1944 len = ( ( endPos ? endPos : p ) - startPos ) / 2; 1945 /* must be even! */ 1946 assert( 2 * len == (ber_len_t) (( endPos ? endPos : p ) - startPos )); 1947 1948 val->bv_len = len; 1949 val->bv_val = LDAP_MALLOCX( len + 1, ctx ); 1950 if ( val->bv_val == NULL ) { 1951 return( LDAP_NO_MEMORY ); 1952 } 1953 1954 for ( s = 0, d = 0; d < len; s += 2, d++ ) { 1955 char c; 1956 1957 hexstr2bin( &startPos[ s ], &c ); 1958 1959 val->bv_val[ d ] = c; 1960 } 1961 1962 val->bv_val[ d ] = '\0'; 1963 1964 return( 0 ); 1965 } 1966 1967 /* 1968 * convert a byte in a hexadecimal pair 1969 */ 1970 static int 1971 byte2hexpair( const char *val, char *pair ) 1972 { 1973 static const char hexdig[] = "0123456789ABCDEF"; 1974 1975 assert( val != NULL ); 1976 assert( pair != NULL ); 1977 1978 /* 1979 * we assume the string has enough room for the hex encoding 1980 * of the value 1981 */ 1982 1983 pair[ 0 ] = hexdig[ 0x0f & ( val[ 0 ] >> 4 ) ]; 1984 pair[ 1 ] = hexdig[ 0x0f & val[ 0 ] ]; 1985 1986 return( 0 ); 1987 } 1988 1989 /* 1990 * convert a binary value in hexadecimal pairs 1991 */ 1992 static int 1993 binval2hexstr( struct berval *val, char *str ) 1994 { 1995 ber_len_t s, d; 1996 1997 assert( val != NULL ); 1998 assert( str != NULL ); 1999 2000 if ( val->bv_len == 0 ) { 2001 return( 0 ); 2002 } 2003 2004 /* 2005 * we assume the string has enough room for the hex encoding 2006 * of the value 2007 */ 2008 2009 for ( s = 0, d = 0; s < val->bv_len; s++, d += 2 ) { 2010 byte2hexpair( &val->bv_val[ s ], &str[ d ] ); 2011 } 2012 2013 return( 0 ); 2014 } 2015 2016 /* 2017 * Length of the string representation, accounting for escaped hex 2018 * of UTF-8 chars 2019 */ 2020 static int 2021 strval2strlen( struct berval *val, unsigned flags, ber_len_t *len ) 2022 { 2023 ber_len_t l, cl = 1; 2024 char *p, *end; 2025 int escaped_byte_len = LDAP_DN_IS_PRETTY( flags ) ? 1 : 3; 2026 #ifdef PRETTY_ESCAPE 2027 int escaped_ascii_len = LDAP_DN_IS_PRETTY( flags ) ? 2 : 3; 2028 #endif /* PRETTY_ESCAPE */ 2029 2030 assert( val != NULL ); 2031 assert( len != NULL ); 2032 2033 *len = 0; 2034 if ( val->bv_len == 0 ) { 2035 return( 0 ); 2036 } 2037 2038 end = val->bv_val + val->bv_len - 1; 2039 for ( l = 0, p = val->bv_val; p <= end; p += cl ) { 2040 2041 /* 2042 * escape '%x00' 2043 */ 2044 if ( p[ 0 ] == '\0' ) { 2045 cl = 1; 2046 l += 3; 2047 continue; 2048 } 2049 2050 cl = LDAP_UTF8_CHARLEN2( p, cl ); 2051 if ( cl == 0 ) { 2052 /* illegal utf-8 char! */ 2053 return( -1 ); 2054 2055 } else if ( cl > 1 ) { 2056 ber_len_t cnt; 2057 2058 for ( cnt = 1; cnt < cl; cnt++ ) { 2059 if ( ( p[ cnt ] & 0xc0 ) != 0x80 ) { 2060 return( -1 ); 2061 } 2062 } 2063 l += escaped_byte_len * cl; 2064 2065 } else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) 2066 || LDAP_DN_SHOULDESCAPE( p[ 0 ] ) 2067 || ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) ) 2068 || ( p == end && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) { 2069 #ifdef PRETTY_ESCAPE 2070 #if 0 2071 if ( LDAP_DN_WILLESCAPE_HEX( flags, p[ 0 ] ) ) { 2072 #else 2073 if ( LDAP_DN_WILLESCAPE_CHAR( p[ 0 ] ) ) { 2074 #endif 2075 2076 /* 2077 * there might be some chars we want 2078 * to escape in form of a couple 2079 * of hexdigits for optimization purposes 2080 */ 2081 l += 3; 2082 2083 } else { 2084 l += escaped_ascii_len; 2085 } 2086 #else /* ! PRETTY_ESCAPE */ 2087 l += 3; 2088 #endif /* ! PRETTY_ESCAPE */ 2089 2090 } else { 2091 l++; 2092 } 2093 } 2094 2095 *len = l; 2096 2097 return( 0 ); 2098 } 2099 2100 /* 2101 * convert to string representation, escaping with hex the UTF-8 stuff; 2102 * assume the destination has enough room for escaping 2103 */ 2104 static int 2105 strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) 2106 { 2107 ber_len_t s, d, end; 2108 2109 assert( val != NULL ); 2110 assert( str != NULL ); 2111 assert( len != NULL ); 2112 2113 if ( val->bv_len == 0 ) { 2114 *len = 0; 2115 return( 0 ); 2116 } 2117 2118 /* 2119 * we assume the string has enough room for the hex encoding 2120 * of the value 2121 */ 2122 for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) { 2123 ber_len_t cl; 2124 2125 /* 2126 * escape '%x00' 2127 */ 2128 if ( val->bv_val[ s ] == '\0' ) { 2129 cl = 1; 2130 str[ d++ ] = '\\'; 2131 str[ d++ ] = '0'; 2132 str[ d++ ] = '0'; 2133 s++; 2134 continue; 2135 } 2136 2137 /* 2138 * The length was checked in strval2strlen(); 2139 */ 2140 cl = LDAP_UTF8_CHARLEN( &val->bv_val[ s ] ); 2141 2142 /* 2143 * there might be some chars we want to escape in form 2144 * of a couple of hexdigits for optimization purposes 2145 */ 2146 if ( ( cl > 1 && !LDAP_DN_IS_PRETTY( flags ) ) 2147 #ifdef PRETTY_ESCAPE 2148 #if 0 2149 || LDAP_DN_WILLESCAPE_HEX( flags, val->bv_val[ s ] ) 2150 #else 2151 || LDAP_DN_WILLESCAPE_CHAR( val->bv_val[ s ] ) 2152 #endif 2153 #else /* ! PRETTY_ESCAPE */ 2154 || LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) 2155 || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] ) 2156 || ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) ) 2157 || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) 2158 2159 #endif /* ! PRETTY_ESCAPE */ 2160 ) { 2161 for ( ; cl--; ) { 2162 str[ d++ ] = '\\'; 2163 byte2hexpair( &val->bv_val[ s ], &str[ d ] ); 2164 s++; 2165 d += 2; 2166 } 2167 2168 } else if ( cl > 1 ) { 2169 for ( ; cl--; ) { 2170 str[ d++ ] = val->bv_val[ s++ ]; 2171 } 2172 2173 } else { 2174 #ifdef PRETTY_ESCAPE 2175 if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) 2176 || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] ) 2177 || ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) ) 2178 || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) { 2179 str[ d++ ] = '\\'; 2180 if ( !LDAP_DN_IS_PRETTY( flags ) ) { 2181 byte2hexpair( &val->bv_val[ s ], &str[ d ] ); 2182 s++; 2183 d += 2; 2184 continue; 2185 } 2186 } 2187 #endif /* PRETTY_ESCAPE */ 2188 str[ d++ ] = val->bv_val[ s++ ]; 2189 } 2190 } 2191 2192 *len = d; 2193 2194 return( 0 ); 2195 } 2196 2197 /* 2198 * Length of the IA5 string representation (no UTF-8 allowed) 2199 */ 2200 static int 2201 strval2IA5strlen( struct berval *val, unsigned flags, ber_len_t *len ) 2202 { 2203 ber_len_t l; 2204 char *p; 2205 2206 assert( val != NULL ); 2207 assert( len != NULL ); 2208 2209 *len = 0; 2210 if ( val->bv_len == 0 ) { 2211 return( 0 ); 2212 } 2213 2214 if ( flags & LDAP_AVA_NONPRINTABLE ) { 2215 /* 2216 * Turn value into a binary encoded BER 2217 */ 2218 return( -1 ); 2219 2220 } else { 2221 for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) { 2222 if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) 2223 || LDAP_DN_SHOULDESCAPE( p[ 0 ] ) 2224 || ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) ) 2225 || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) { 2226 l += 2; 2227 2228 } else { 2229 l++; 2230 } 2231 } 2232 } 2233 2234 *len = l; 2235 2236 return( 0 ); 2237 } 2238 2239 /* 2240 * convert to string representation (np UTF-8) 2241 * assume the destination has enough room for escaping 2242 */ 2243 static int 2244 strval2IA5str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) 2245 { 2246 ber_len_t s, d, end; 2247 2248 assert( val != NULL ); 2249 assert( str != NULL ); 2250 assert( len != NULL ); 2251 2252 if ( val->bv_len == 0 ) { 2253 *len = 0; 2254 return( 0 ); 2255 } 2256 2257 if ( flags & LDAP_AVA_NONPRINTABLE ) { 2258 /* 2259 * Turn value into a binary encoded BER 2260 */ 2261 *len = 0; 2262 return( -1 ); 2263 2264 } else { 2265 /* 2266 * we assume the string has enough room for the hex encoding 2267 * of the value 2268 */ 2269 2270 for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) { 2271 if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) 2272 || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] ) 2273 || ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) ) 2274 || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) { 2275 str[ d++ ] = '\\'; 2276 } 2277 str[ d++ ] = val->bv_val[ s++ ]; 2278 } 2279 } 2280 2281 *len = d; 2282 2283 return( 0 ); 2284 } 2285 2286 /* 2287 * Length of the (supposedly) DCE string representation, 2288 * accounting for escaped hex of UTF-8 chars 2289 */ 2290 static int 2291 strval2DCEstrlen( struct berval *val, unsigned flags, ber_len_t *len ) 2292 { 2293 ber_len_t l; 2294 char *p; 2295 2296 assert( val != NULL ); 2297 assert( len != NULL ); 2298 2299 *len = 0; 2300 if ( val->bv_len == 0 ) { 2301 return( 0 ); 2302 } 2303 2304 if ( flags & LDAP_AVA_NONPRINTABLE ) { 2305 /* 2306 * FIXME: Turn the value into a binary encoded BER? 2307 */ 2308 return( -1 ); 2309 2310 } else { 2311 for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) { 2312 if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) { 2313 l += 2; 2314 2315 } else { 2316 l++; 2317 } 2318 } 2319 } 2320 2321 *len = l; 2322 2323 return( 0 ); 2324 } 2325 2326 /* 2327 * convert to (supposedly) DCE string representation, 2328 * escaping with hex the UTF-8 stuff; 2329 * assume the destination has enough room for escaping 2330 */ 2331 static int 2332 strval2DCEstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ) 2333 { 2334 ber_len_t s, d; 2335 2336 assert( val != NULL ); 2337 assert( str != NULL ); 2338 assert( len != NULL ); 2339 2340 if ( val->bv_len == 0 ) { 2341 *len = 0; 2342 return( 0 ); 2343 } 2344 2345 if ( flags & LDAP_AVA_NONPRINTABLE ) { 2346 /* 2347 * FIXME: Turn the value into a binary encoded BER? 2348 */ 2349 *len = 0; 2350 return( -1 ); 2351 2352 } else { 2353 2354 /* 2355 * we assume the string has enough room for the hex encoding 2356 * of the value 2357 */ 2358 2359 for ( s = 0, d = 0; s < val->bv_len; ) { 2360 if ( LDAP_DN_NEEDESCAPE_DCE( val->bv_val[ s ] ) ) { 2361 str[ d++ ] = '\\'; 2362 } 2363 str[ d++ ] = val->bv_val[ s++ ]; 2364 } 2365 } 2366 2367 *len = d; 2368 2369 return( 0 ); 2370 } 2371 2372 /* 2373 * Length of the (supposedly) AD canonical string representation, 2374 * accounting for chars that need to be escaped 2375 */ 2376 static int 2377 strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len ) 2378 { 2379 ber_len_t l, cl; 2380 char *p; 2381 2382 assert( val != NULL ); 2383 assert( len != NULL ); 2384 2385 *len = 0; 2386 if ( val->bv_len == 0 ) { 2387 return( 0 ); 2388 } 2389 2390 for ( l = 0, p = val->bv_val; p[ 0 ]; p += cl ) { 2391 cl = LDAP_UTF8_CHARLEN2( p, cl ); 2392 if ( cl == 0 ) { 2393 /* illegal utf-8 char */ 2394 return -1; 2395 } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) { 2396 l += 2; 2397 } else { 2398 l += cl; 2399 } 2400 } 2401 2402 *len = l; 2403 2404 return( 0 ); 2405 } 2406 2407 /* 2408 * convert to (supposedly) AD string representation, 2409 * assume the destination has enough room for escaping 2410 */ 2411 static int 2412 strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ) 2413 { 2414 ber_len_t s, d, cl; 2415 2416 assert( val != NULL ); 2417 assert( str != NULL ); 2418 assert( len != NULL ); 2419 2420 if ( val->bv_len == 0 ) { 2421 *len = 0; 2422 return( 0 ); 2423 } 2424 2425 /* 2426 * we assume the string has enough room for the escaping 2427 * of the value 2428 */ 2429 2430 for ( s = 0, d = 0; s < val->bv_len; ) { 2431 cl = LDAP_UTF8_CHARLEN2( val->bv_val+s, cl ); 2432 if ( cl == 0 ) { 2433 /* illegal utf-8 char */ 2434 return -1; 2435 } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD(val->bv_val[ s ]) ) { 2436 str[ d++ ] = '\\'; 2437 } 2438 for (; cl--;) { 2439 str[ d++ ] = val->bv_val[ s++ ]; 2440 } 2441 } 2442 2443 *len = d; 2444 2445 return( 0 ); 2446 } 2447 2448 /* 2449 * If the DN is terminated by single-AVA RDNs with attribute type of "dc", 2450 * the first part of the AD representation of the DN is written in DNS 2451 * form, i.e. dot separated domain name components (as suggested 2452 * by Luke Howard, http://www.padl.com/~lukeh) 2453 */ 2454 static int 2455 dn2domain( LDAPDN dn, struct berval *bv, int pos, int *iRDN ) 2456 { 2457 int i; 2458 int domain = 0, first = 1; 2459 ber_len_t l = 1; /* we move the null also */ 2460 char *str; 2461 2462 /* we are guaranteed there's enough memory in str */ 2463 2464 /* sanity */ 2465 assert( dn != NULL ); 2466 assert( bv != NULL ); 2467 assert( iRDN != NULL ); 2468 assert( *iRDN >= 0 ); 2469 2470 str = bv->bv_val + pos; 2471 2472 for ( i = *iRDN; i >= 0; i-- ) { 2473 LDAPRDN rdn; 2474 LDAPAVA *ava; 2475 2476 assert( dn[ i ] != NULL ); 2477 rdn = dn[ i ]; 2478 2479 assert( rdn[ 0 ] != NULL ); 2480 ava = rdn[ 0 ]; 2481 2482 if ( !LDAP_DN_IS_RDN_DC( rdn ) ) { 2483 break; 2484 } 2485 2486 domain = 1; 2487 2488 if ( first ) { 2489 first = 0; 2490 AC_MEMCPY( str, ava->la_value.bv_val, 2491 ava->la_value.bv_len + 1); 2492 l += ava->la_value.bv_len; 2493 2494 } else { 2495 AC_MEMCPY( str + ava->la_value.bv_len + 1, bv->bv_val + pos, l); 2496 AC_MEMCPY( str, ava->la_value.bv_val, 2497 ava->la_value.bv_len ); 2498 str[ ava->la_value.bv_len ] = '.'; 2499 l += ava->la_value.bv_len + 1; 2500 } 2501 } 2502 2503 *iRDN = i; 2504 bv->bv_len = pos + l - 1; 2505 2506 return( domain ); 2507 } 2508 2509 static int 2510 rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len, 2511 int ( *s2l )( struct berval *v, unsigned f, ber_len_t *l ) ) 2512 { 2513 int iAVA; 2514 ber_len_t l = 0; 2515 2516 *len = 0; 2517 2518 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { 2519 LDAPAVA *ava = rdn[ iAVA ]; 2520 2521 /* len(type) + '=' + '+' | ',' */ 2522 l += ava->la_attr.bv_len + 2; 2523 2524 if ( ava->la_flags & LDAP_AVA_BINARY ) { 2525 /* octothorpe + twice the length */ 2526 l += 1 + 2 * ava->la_value.bv_len; 2527 2528 } else { 2529 ber_len_t vl; 2530 unsigned f = flags | ava->la_flags; 2531 2532 if ( ( *s2l )( &ava->la_value, f, &vl ) ) { 2533 return( -1 ); 2534 } 2535 l += vl; 2536 } 2537 } 2538 2539 *len = l; 2540 2541 return( 0 ); 2542 } 2543 2544 static int 2545 rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, 2546 int ( *s2s ) ( struct berval *v, char * s, unsigned f, ber_len_t *l ) ) 2547 { 2548 int iAVA; 2549 ber_len_t l = 0; 2550 2551 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { 2552 LDAPAVA *ava = rdn[ iAVA ]; 2553 2554 AC_MEMCPY( &str[ l ], ava->la_attr.bv_val, 2555 ava->la_attr.bv_len ); 2556 l += ava->la_attr.bv_len; 2557 2558 str[ l++ ] = '='; 2559 2560 if ( ava->la_flags & LDAP_AVA_BINARY ) { 2561 str[ l++ ] = '#'; 2562 if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { 2563 return( -1 ); 2564 } 2565 l += 2 * ava->la_value.bv_len; 2566 2567 } else { 2568 ber_len_t vl; 2569 unsigned f = flags | ava->la_flags; 2570 2571 if ( ( *s2s )( &ava->la_value, &str[ l ], f, &vl ) ) { 2572 return( -1 ); 2573 } 2574 l += vl; 2575 } 2576 str[ l++ ] = ( rdn[ iAVA + 1] ? '+' : ',' ); 2577 } 2578 2579 *len = l; 2580 2581 return( 0 ); 2582 } 2583 2584 static int 2585 rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ) 2586 { 2587 int iAVA; 2588 ber_len_t l = 0; 2589 2590 *len = 0; 2591 2592 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { 2593 LDAPAVA *ava = rdn[ iAVA ]; 2594 2595 /* len(type) + '=' + ',' | '/' */ 2596 l += ava->la_attr.bv_len + 2; 2597 2598 if ( ava->la_flags & LDAP_AVA_BINARY ) { 2599 /* octothorpe + twice the length */ 2600 l += 1 + 2 * ava->la_value.bv_len; 2601 } else { 2602 ber_len_t vl; 2603 unsigned f = flags | ava->la_flags; 2604 2605 if ( strval2DCEstrlen( &ava->la_value, f, &vl ) ) { 2606 return( -1 ); 2607 } 2608 l += vl; 2609 } 2610 } 2611 2612 *len = l; 2613 2614 return( 0 ); 2615 } 2616 2617 static int 2618 rdn2DCEstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first ) 2619 { 2620 int iAVA; 2621 ber_len_t l = 0; 2622 2623 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { 2624 LDAPAVA *ava = rdn[ iAVA ]; 2625 2626 if ( first ) { 2627 first = 0; 2628 } else { 2629 str[ l++ ] = ( iAVA ? ',' : '/' ); 2630 } 2631 2632 AC_MEMCPY( &str[ l ], ava->la_attr.bv_val, 2633 ava->la_attr.bv_len ); 2634 l += ava->la_attr.bv_len; 2635 2636 str[ l++ ] = '='; 2637 2638 if ( ava->la_flags & LDAP_AVA_BINARY ) { 2639 str[ l++ ] = '#'; 2640 if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { 2641 return( -1 ); 2642 } 2643 l += 2 * ava->la_value.bv_len; 2644 } else { 2645 ber_len_t vl; 2646 unsigned f = flags | ava->la_flags; 2647 2648 if ( strval2DCEstr( &ava->la_value, &str[ l ], f, &vl ) ) { 2649 return( -1 ); 2650 } 2651 l += vl; 2652 } 2653 } 2654 2655 *len = l; 2656 2657 return( 0 ); 2658 } 2659 2660 static int 2661 rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ) 2662 { 2663 int iAVA; 2664 ber_len_t l = 0; 2665 2666 assert( rdn != NULL ); 2667 assert( len != NULL ); 2668 2669 *len = 0; 2670 2671 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { 2672 LDAPAVA *ava = rdn[ iAVA ]; 2673 2674 /* ' + ' | ', ' */ 2675 l += ( rdn[ iAVA + 1 ] ? 3 : 2 ); 2676 2677 /* FIXME: are binary values allowed in UFN? */ 2678 if ( ava->la_flags & LDAP_AVA_BINARY ) { 2679 /* octothorpe + twice the value */ 2680 l += 1 + 2 * ava->la_value.bv_len; 2681 2682 } else { 2683 ber_len_t vl; 2684 unsigned f = flags | ava->la_flags; 2685 2686 if ( strval2strlen( &ava->la_value, f, &vl ) ) { 2687 return( -1 ); 2688 } 2689 l += vl; 2690 } 2691 } 2692 2693 *len = l; 2694 2695 return( 0 ); 2696 } 2697 2698 static int 2699 rdn2UFNstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len ) 2700 { 2701 int iAVA; 2702 ber_len_t l = 0; 2703 2704 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { 2705 LDAPAVA *ava = rdn[ iAVA ]; 2706 2707 if ( ava->la_flags & LDAP_AVA_BINARY ) { 2708 str[ l++ ] = '#'; 2709 if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { 2710 return( -1 ); 2711 } 2712 l += 2 * ava->la_value.bv_len; 2713 2714 } else { 2715 ber_len_t vl; 2716 unsigned f = flags | ava->la_flags; 2717 2718 if ( strval2str( &ava->la_value, &str[ l ], f, &vl ) ) { 2719 return( -1 ); 2720 } 2721 l += vl; 2722 } 2723 2724 if ( rdn[ iAVA + 1 ] ) { 2725 AC_MEMCPY( &str[ l ], " + ", 3 ); 2726 l += 3; 2727 2728 } else { 2729 AC_MEMCPY( &str[ l ], ", ", 2 ); 2730 l += 2; 2731 } 2732 } 2733 2734 *len = l; 2735 2736 return( 0 ); 2737 } 2738 2739 static int 2740 rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ) 2741 { 2742 int iAVA; 2743 ber_len_t l = 0; 2744 2745 assert( rdn != NULL ); 2746 assert( len != NULL ); 2747 2748 *len = 0; 2749 2750 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { 2751 LDAPAVA *ava = rdn[ iAVA ]; 2752 2753 /* ',' | '/' */ 2754 l++; 2755 2756 /* FIXME: are binary values allowed in UFN? */ 2757 if ( ava->la_flags & LDAP_AVA_BINARY ) { 2758 /* octothorpe + twice the value */ 2759 l += 1 + 2 * ava->la_value.bv_len; 2760 } else { 2761 ber_len_t vl; 2762 unsigned f = flags | ava->la_flags; 2763 2764 if ( strval2ADstrlen( &ava->la_value, f, &vl ) ) { 2765 return( -1 ); 2766 } 2767 l += vl; 2768 } 2769 } 2770 2771 *len = l; 2772 2773 return( 0 ); 2774 } 2775 2776 static int 2777 rdn2ADstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first ) 2778 { 2779 int iAVA; 2780 ber_len_t l = 0; 2781 2782 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { 2783 LDAPAVA *ava = rdn[ iAVA ]; 2784 2785 if ( first ) { 2786 first = 0; 2787 } else { 2788 str[ l++ ] = ( iAVA ? ',' : '/' ); 2789 } 2790 2791 if ( ava->la_flags & LDAP_AVA_BINARY ) { 2792 str[ l++ ] = '#'; 2793 if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { 2794 return( -1 ); 2795 } 2796 l += 2 * ava->la_value.bv_len; 2797 } else { 2798 ber_len_t vl; 2799 unsigned f = flags | ava->la_flags; 2800 2801 if ( strval2ADstr( &ava->la_value, &str[ l ], f, &vl ) ) { 2802 return( -1 ); 2803 } 2804 l += vl; 2805 } 2806 } 2807 2808 *len = l; 2809 2810 return( 0 ); 2811 } 2812 2813 /* 2814 * ldap_rdn2str 2815 * 2816 * Returns in str a string representation of rdn based on flags. 2817 * There is some duplication of code between this and ldap_dn2str; 2818 * this is wanted to reduce the allocation of temporary buffers. 2819 */ 2820 int 2821 ldap_rdn2str( LDAPRDN rdn, char **str, unsigned flags ) 2822 { 2823 struct berval bv; 2824 int rc; 2825 2826 assert( str != NULL ); 2827 2828 if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) { 2829 return LDAP_PARAM_ERROR; 2830 } 2831 2832 rc = ldap_rdn2bv_x( rdn, &bv, flags, NULL ); 2833 *str = bv.bv_val; 2834 return rc; 2835 } 2836 2837 int 2838 ldap_rdn2bv( LDAPRDN rdn, struct berval *bv, unsigned flags ) 2839 { 2840 return ldap_rdn2bv_x( rdn, bv, flags, NULL ); 2841 } 2842 2843 int 2844 ldap_rdn2bv_x( LDAPRDN rdn, struct berval *bv, unsigned flags, void *ctx ) 2845 { 2846 int rc, back; 2847 ber_len_t l; 2848 2849 assert( bv != NULL ); 2850 2851 bv->bv_len = 0; 2852 bv->bv_val = NULL; 2853 2854 if ( rdn == NULL ) { 2855 bv->bv_val = LDAP_STRDUPX( "", ctx ); 2856 return( LDAP_SUCCESS ); 2857 } 2858 2859 /* 2860 * This routine wastes "back" bytes at the end of the string 2861 */ 2862 2863 switch ( LDAP_DN_FORMAT( flags ) ) { 2864 case LDAP_DN_FORMAT_LDAPV3: 2865 if ( rdn2strlen( rdn, flags, &l, strval2strlen ) ) { 2866 return LDAP_DECODING_ERROR; 2867 } 2868 break; 2869 2870 case LDAP_DN_FORMAT_LDAPV2: 2871 if ( rdn2strlen( rdn, flags, &l, strval2IA5strlen ) ) { 2872 return LDAP_DECODING_ERROR; 2873 } 2874 break; 2875 2876 case LDAP_DN_FORMAT_UFN: 2877 if ( rdn2UFNstrlen( rdn, flags, &l ) ) { 2878 return LDAP_DECODING_ERROR; 2879 } 2880 break; 2881 2882 case LDAP_DN_FORMAT_DCE: 2883 if ( rdn2DCEstrlen( rdn, flags, &l ) ) { 2884 return LDAP_DECODING_ERROR; 2885 } 2886 break; 2887 2888 case LDAP_DN_FORMAT_AD_CANONICAL: 2889 if ( rdn2ADstrlen( rdn, flags, &l ) ) { 2890 return LDAP_DECODING_ERROR; 2891 } 2892 break; 2893 2894 default: 2895 return LDAP_PARAM_ERROR; 2896 } 2897 2898 bv->bv_val = LDAP_MALLOCX( l + 1, ctx ); 2899 2900 switch ( LDAP_DN_FORMAT( flags ) ) { 2901 case LDAP_DN_FORMAT_LDAPV3: 2902 rc = rdn2str( rdn, bv->bv_val, flags, &l, strval2str ); 2903 back = 1; 2904 break; 2905 2906 case LDAP_DN_FORMAT_LDAPV2: 2907 rc = rdn2str( rdn, bv->bv_val, flags, &l, strval2IA5str ); 2908 back = 1; 2909 break; 2910 2911 case LDAP_DN_FORMAT_UFN: 2912 rc = rdn2UFNstr( rdn, bv->bv_val, flags, &l ); 2913 back = 2; 2914 break; 2915 2916 case LDAP_DN_FORMAT_DCE: 2917 rc = rdn2DCEstr( rdn, bv->bv_val, flags, &l, 1 ); 2918 back = 0; 2919 break; 2920 2921 case LDAP_DN_FORMAT_AD_CANONICAL: 2922 rc = rdn2ADstr( rdn, bv->bv_val, flags, &l, 1 ); 2923 back = 0; 2924 break; 2925 2926 default: 2927 /* need at least one of the previous */ 2928 return LDAP_PARAM_ERROR; 2929 } 2930 2931 if ( rc ) { 2932 LDAP_FREEX( bv->bv_val, ctx ); 2933 return rc; 2934 } 2935 2936 bv->bv_len = l - back; 2937 bv->bv_val[ bv->bv_len ] = '\0'; 2938 2939 return LDAP_SUCCESS; 2940 } 2941 2942 /* 2943 * Very bulk implementation; many optimizations can be performed 2944 * - a NULL dn results in an empty string "" 2945 * 2946 * FIXME: doubts 2947 * a) what do we do if a UTF-8 string must be converted in LDAPv2? 2948 * we must encode it in binary form ('#' + HEXPAIRs) 2949 * b) does DCE/AD support UTF-8? 2950 * no clue; don't think so. 2951 * c) what do we do when binary values must be converted in UTF/DCE/AD? 2952 * use binary encoded BER 2953 */ 2954 int ldap_dn2str( LDAPDN dn, char **str, unsigned flags ) 2955 { 2956 struct berval bv; 2957 int rc; 2958 2959 assert( str != NULL ); 2960 2961 if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) { 2962 return LDAP_PARAM_ERROR; 2963 } 2964 2965 rc = ldap_dn2bv_x( dn, &bv, flags, NULL ); 2966 *str = bv.bv_val; 2967 return rc; 2968 } 2969 2970 int ldap_dn2bv( LDAPDN dn, struct berval *bv, unsigned flags ) 2971 { 2972 return ldap_dn2bv_x( dn, bv, flags, NULL ); 2973 } 2974 2975 int ldap_dn2bv_x( LDAPDN dn, struct berval *bv, unsigned flags, void *ctx ) 2976 { 2977 int iRDN; 2978 int rc = LDAP_ENCODING_ERROR; 2979 ber_len_t len, l; 2980 2981 /* stringifying helpers for LDAPv3/LDAPv2 */ 2982 int ( *sv2l ) ( struct berval *v, unsigned f, ber_len_t *l ); 2983 int ( *sv2s ) ( struct berval *v, char *s, unsigned f, ber_len_t *l ); 2984 2985 assert( bv != NULL ); 2986 bv->bv_len = 0; 2987 bv->bv_val = NULL; 2988 2989 Debug( LDAP_DEBUG_ARGS, "=> ldap_dn2bv(%u)\n", flags, 0, 0 ); 2990 2991 /* 2992 * a null dn means an empty dn string 2993 * FIXME: better raise an error? 2994 */ 2995 if ( dn == NULL || dn[0] == NULL ) { 2996 bv->bv_val = LDAP_STRDUPX( "", ctx ); 2997 return( LDAP_SUCCESS ); 2998 } 2999 3000 switch ( LDAP_DN_FORMAT( flags ) ) { 3001 case LDAP_DN_FORMAT_LDAPV3: 3002 sv2l = strval2strlen; 3003 sv2s = strval2str; 3004 3005 if( 0 ) { 3006 case LDAP_DN_FORMAT_LDAPV2: 3007 sv2l = strval2IA5strlen; 3008 sv2s = strval2IA5str; 3009 } 3010 3011 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) { 3012 ber_len_t rdnl; 3013 if ( rdn2strlen( dn[ iRDN ], flags, &rdnl, sv2l ) ) { 3014 goto return_results; 3015 } 3016 3017 len += rdnl; 3018 } 3019 3020 if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) { 3021 rc = LDAP_NO_MEMORY; 3022 break; 3023 } 3024 3025 for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) { 3026 ber_len_t rdnl; 3027 3028 if ( rdn2str( dn[ iRDN ], &bv->bv_val[ l ], flags, 3029 &rdnl, sv2s ) ) { 3030 LDAP_FREEX( bv->bv_val, ctx ); 3031 bv->bv_val = NULL; 3032 goto return_results; 3033 } 3034 l += rdnl; 3035 } 3036 3037 assert( l == len ); 3038 3039 /* 3040 * trim the last ',' (the allocated memory 3041 * is one byte longer than required) 3042 */ 3043 bv->bv_len = len - 1; 3044 bv->bv_val[ bv->bv_len ] = '\0'; 3045 3046 rc = LDAP_SUCCESS; 3047 break; 3048 3049 case LDAP_DN_FORMAT_UFN: { 3050 /* 3051 * FIXME: quoting from RFC 1781: 3052 * 3053 To take a distinguished name, and generate a name of this format with 3054 attribute types omitted, the following steps are followed. 3055 3056 1. If the first attribute is of type CommonName, the type may be 3057 omitted. 3058 3059 2. If the last attribute is of type Country, the type may be 3060 omitted. 3061 3062 3. If the last attribute is of type Country, the last 3063 Organisation attribute may have the type omitted. 3064 3065 4. All attributes of type OrganisationalUnit may have the type 3066 omitted, unless they are after an Organisation attribute or 3067 the first attribute is of type OrganisationalUnit. 3068 3069 * this should be the pedantic implementation. 3070 * 3071 * Here the standard implementation reflects 3072 * the one historically provided by OpenLDAP 3073 * (and UMIch, I presume), with the variant 3074 * of spaces and plusses (' + ') separating 3075 * rdn components. 3076 * 3077 * A non-standard but nice implementation could 3078 * be to turn the final "dc" attributes into a 3079 * dot-separated domain. 3080 * 3081 * Other improvements could involve the use of 3082 * friendly country names and so. 3083 */ 3084 #ifdef DC_IN_UFN 3085 int leftmost_dc = -1; 3086 int last_iRDN = -1; 3087 #endif /* DC_IN_UFN */ 3088 3089 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) { 3090 ber_len_t rdnl; 3091 3092 if ( rdn2UFNstrlen( dn[ iRDN ], flags, &rdnl ) ) { 3093 goto return_results; 3094 } 3095 len += rdnl; 3096 3097 #ifdef DC_IN_UFN 3098 if ( LDAP_DN_IS_RDN_DC( dn[ iRDN ] ) ) { 3099 if ( leftmost_dc == -1 ) { 3100 leftmost_dc = iRDN; 3101 } 3102 } else { 3103 leftmost_dc = -1; 3104 } 3105 #endif /* DC_IN_UFN */ 3106 } 3107 3108 if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) { 3109 rc = LDAP_NO_MEMORY; 3110 break; 3111 } 3112 3113 #ifdef DC_IN_UFN 3114 if ( leftmost_dc == -1 ) { 3115 #endif /* DC_IN_UFN */ 3116 for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) { 3117 ber_len_t vl; 3118 3119 if ( rdn2UFNstr( dn[ iRDN ], &bv->bv_val[ l ], 3120 flags, &vl ) ) { 3121 LDAP_FREEX( bv->bv_val, ctx ); 3122 bv->bv_val = NULL; 3123 goto return_results; 3124 } 3125 l += vl; 3126 } 3127 3128 /* 3129 * trim the last ', ' (the allocated memory 3130 * is two bytes longer than required) 3131 */ 3132 bv->bv_len = len - 2; 3133 bv->bv_val[ bv->bv_len ] = '\0'; 3134 #ifdef DC_IN_UFN 3135 } else { 3136 last_iRDN = iRDN - 1; 3137 3138 for ( l = 0, iRDN = 0; iRDN < leftmost_dc; iRDN++ ) { 3139 ber_len_t vl; 3140 3141 if ( rdn2UFNstr( dn[ iRDN ], &bv->bv_val[ l ], 3142 flags, &vl ) ) { 3143 LDAP_FREEX( bv->bv_val, ctx ); 3144 bv->bv_val = NULL; 3145 goto return_results; 3146 } 3147 l += vl; 3148 } 3149 3150 if ( !dn2domain( dn, bv, l, &last_iRDN ) ) { 3151 LDAP_FREEX( bv->bv_val, ctx ); 3152 bv->bv_val = NULL; 3153 goto return_results; 3154 } 3155 3156 /* the string is correctly terminated by dn2domain */ 3157 } 3158 #endif /* DC_IN_UFN */ 3159 3160 rc = LDAP_SUCCESS; 3161 3162 } break; 3163 3164 case LDAP_DN_FORMAT_DCE: 3165 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) { 3166 ber_len_t rdnl; 3167 if ( rdn2DCEstrlen( dn[ iRDN ], flags, &rdnl ) ) { 3168 goto return_results; 3169 } 3170 3171 len += rdnl; 3172 } 3173 3174 if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) { 3175 rc = LDAP_NO_MEMORY; 3176 break; 3177 } 3178 3179 for ( l = 0; iRDN--; ) { 3180 ber_len_t rdnl; 3181 3182 if ( rdn2DCEstr( dn[ iRDN ], &bv->bv_val[ l ], flags, 3183 &rdnl, 0 ) ) { 3184 LDAP_FREEX( bv->bv_val, ctx ); 3185 bv->bv_val = NULL; 3186 goto return_results; 3187 } 3188 l += rdnl; 3189 } 3190 3191 assert( l == len ); 3192 3193 bv->bv_len = len; 3194 bv->bv_val[ bv->bv_len ] = '\0'; 3195 3196 rc = LDAP_SUCCESS; 3197 break; 3198 3199 case LDAP_DN_FORMAT_AD_CANONICAL: { 3200 int trailing_slash = 1; 3201 3202 /* 3203 * Sort of UFN for DCE DNs: a slash ('/') separated 3204 * global->local DN with no types; strictly speaking, 3205 * the naming context should be a domain, which is 3206 * written in DNS-style, e.g. dot-deparated. 3207 * 3208 * Example: 3209 * 3210 * "givenName=Bill+sn=Gates,ou=People,dc=microsoft,dc=com" 3211 * 3212 * will read 3213 * 3214 * "microsoft.com/People/Bill,Gates" 3215 */ 3216 for ( iRDN = 0, len = -1; dn[ iRDN ]; iRDN++ ) { 3217 ber_len_t rdnl; 3218 3219 if ( rdn2ADstrlen( dn[ iRDN ], flags, &rdnl ) ) { 3220 goto return_results; 3221 } 3222 3223 len += rdnl; 3224 } 3225 3226 /* reserve room for trailing '/' in case the DN 3227 * is exactly a domain */ 3228 if ( ( bv->bv_val = LDAP_MALLOCX( len + 1 + 1, ctx ) ) == NULL ) 3229 { 3230 rc = LDAP_NO_MEMORY; 3231 break; 3232 } 3233 3234 iRDN--; 3235 if ( iRDN && dn2domain( dn, bv, 0, &iRDN ) != 0 ) { 3236 for ( l = bv->bv_len; iRDN >= 0 ; iRDN-- ) { 3237 ber_len_t rdnl; 3238 3239 trailing_slash = 0; 3240 3241 if ( rdn2ADstr( dn[ iRDN ], &bv->bv_val[ l ], 3242 flags, &rdnl, 0 ) ) { 3243 LDAP_FREEX( bv->bv_val, ctx ); 3244 bv->bv_val = NULL; 3245 goto return_results; 3246 } 3247 l += rdnl; 3248 } 3249 3250 } else { 3251 int first = 1; 3252 3253 /* 3254 * Strictly speaking, AD canonical requires 3255 * a DN to be in the form "..., dc=smtg", 3256 * i.e. terminated by a domain component 3257 */ 3258 if ( flags & LDAP_DN_PEDANTIC ) { 3259 LDAP_FREEX( bv->bv_val, ctx ); 3260 bv->bv_val = NULL; 3261 rc = LDAP_ENCODING_ERROR; 3262 break; 3263 } 3264 3265 for ( l = 0; iRDN >= 0 ; iRDN-- ) { 3266 ber_len_t rdnl; 3267 3268 if ( rdn2ADstr( dn[ iRDN ], &bv->bv_val[ l ], 3269 flags, &rdnl, first ) ) { 3270 LDAP_FREEX( bv->bv_val, ctx ); 3271 bv->bv_val = NULL; 3272 goto return_results; 3273 } 3274 if ( first ) { 3275 first = 0; 3276 } 3277 l += rdnl; 3278 } 3279 } 3280 3281 if ( trailing_slash ) { 3282 /* the DN is exactly a domain -- need a trailing 3283 * slash; room was reserved in advance */ 3284 bv->bv_val[ len ] = '/'; 3285 len++; 3286 } 3287 3288 bv->bv_len = len; 3289 bv->bv_val[ bv->bv_len ] = '\0'; 3290 3291 rc = LDAP_SUCCESS; 3292 } break; 3293 3294 default: 3295 return LDAP_PARAM_ERROR; 3296 } 3297 3298 Debug( LDAP_DEBUG_ARGS, "<= ldap_dn2bv(%s)=%d %s\n", 3299 bv->bv_val, rc, rc ? ldap_err2string( rc ) : "" ); 3300 3301 return_results:; 3302 return( rc ); 3303 } 3304 3305