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