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