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