1 /* The following code comes from the OpenLDAP project. The references
2 to the COPYRIGHT file below refer to the corresponding file in the
3 OpenLDAP distribution, which is reproduced here in full:
4
5 Copyright 1998-2004 The OpenLDAP Foundation
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted only as authorized by the OpenLDAP
10 Public License.
11
12 A copy of this license is available in the file LICENSE in the
13 top-level directory of the distribution or, alternatively, at
14 <http://www.OpenLDAP.org/license.html>.
15
16 OpenLDAP is a registered trademark of the OpenLDAP Foundation.
17
18 Individual files and/or contributed packages may be copyright by
19 other parties and subject to additional restrictions.
20
21 This work is derived from the University of Michigan LDAP v3.3
22 distribution. Information concerning this software is available
23 at <http://www.umich.edu/~dirsvcs/ldap/>.
24
25 This work also contains materials derived from public sources.
26
27 Additional information about OpenLDAP can be obtained at
28 <http://www.openldap.org/>.
29
30 ---
31
32 Portions Copyright 1998-2004 Kurt D. Zeilenga.
33 Portions Copyright 1998-2004 Net Boolean Incorporated.
34 Portions Copyright 2001-2004 IBM Corporation.
35 All rights reserved.
36
37 Redistribution and use in source and binary forms, with or without
38 modification, are permitted only as authorized by the OpenLDAP
39 Public License.
40
41 ---
42
43 Portions Copyright 1999-2003 Howard Y.H. Chu.
44 Portions Copyright 1999-2003 Symas Corporation.
45 Portions Copyright 1998-2003 Hallvard B. Furuseth.
46 All rights reserved.
47
48 Redistribution and use in source and binary forms, with or without
49 modification, are permitted provided that this notice is preserved.
50 The names of the copyright holders may not be used to endorse or
51 promote products derived from this software without their specific
52 prior written permission. This software is provided `'as is''
53 without express or implied warranty.
54
55 ---
56
57 Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
58 All rights reserved.
59
60 Redistribution and use in source and binary forms are permitted
61 provided that this notice is preserved and that due credit is given
62 to the University of Michigan at Ann Arbor. The name of the
63 University may not be used to endorse or promote products derived
64 from this software without specific prior written permission. This
65 software is provided `'as is'' without express or implied warranty. */
66
67
68 #include <config.h>
69 #include <assert.h>
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <time.h>
74
75 #include <winsock2.h>
76 #include <winldap.h>
77 #include "ldap-url.h"
78 #define LDAP_P(protos) protos
79 #define LDAP_URL_URLCOLON "URL:"
80 #define LDAP_URL_URLCOLON_LEN (sizeof(LDAP_URL_URLCOLON)-1)
81 #define LDAP_URL_PREFIX "ldap://"
82 #define LDAP_URL_PREFIX_LEN (sizeof(LDAP_URL_PREFIX)-1)
83 #define LDAPS_URL_PREFIX "ldaps://"
84 #define LDAPS_URL_PREFIX_LEN (sizeof(LDAPS_URL_PREFIX)-1)
85 #define LDAPI_URL_PREFIX "ldapi://"
86 #define LDAPI_URL_PREFIX_LEN (sizeof(LDAPI_URL_PREFIX)-1)
87 #define LDAP_VFREE(v) { int _i; for (_i = 0; (v)[_i]; _i++) free((v)[_i]); }
88 #define LDAP_FREE free
89 #define LDAP_STRDUP strdup
90 #define LDAP_CALLOC calloc
91 #define LDAP_MALLOC malloc
92 #define LDAP_REALLOC realloc
93 #define ldap_utf8_strchr strchr
94 #define ldap_utf8_strtok(n,d) strtok (n,d)
95 #define Debug(a,b,c,d,e)
96 void ldap_pvt_hex_unescape( char *s );
97
98
99 #ifndef LDAP_SCOPE_DEFAULT
100 # define LDAP_SCOPE_DEFAULT -1
101 #endif
102
103
104
105 /* $OpenLDAP: pkg/ldap/libraries/libldap/charray.c,v 1.9.2.2 2003/03/03 17:10:04 kurt Exp $ */
106 /*
107 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
108 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
109 */
110 /* charray.c - routines for dealing with char * arrays */
111
112 int
ldap_charray_add(char *** a,char * s)113 ldap_charray_add(
114 char ***a,
115 char *s
116 )
117 {
118 int n;
119
120 if ( *a == NULL ) {
121 *a = (char **) LDAP_MALLOC( 2 * sizeof(char *) );
122 n = 0;
123
124 if( *a == NULL ) {
125 return -1;
126 }
127
128 } else {
129 char **new;
130
131 for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
132 ; /* NULL */
133 }
134
135 new = (char **) LDAP_REALLOC( (char *) *a,
136 (n + 2) * sizeof(char *) );
137
138 if( new == NULL ) {
139 /* caller is required to call ldap_charray_free(*a) */
140 return -1;
141 }
142
143 *a = new;
144 }
145
146 (*a)[n] = LDAP_STRDUP(s);
147
148 if( (*a)[n] == NULL ) {
149 return 1;
150 }
151
152 (*a)[++n] = NULL;
153
154 return 0;
155 }
156
157 int
ldap_charray_merge(char *** a,char ** s)158 ldap_charray_merge(
159 char ***a,
160 char **s
161 )
162 {
163 int i, n, nn;
164 char **aa;
165
166 for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
167 ; /* NULL */
168 }
169 for ( nn = 0; s[nn] != NULL; nn++ ) {
170 ; /* NULL */
171 }
172
173 aa = (char **) LDAP_REALLOC( (char *) *a, (n + nn + 1) * sizeof(char *) );
174
175 if( aa == NULL ) {
176 return -1;
177 }
178
179 *a = aa;
180
181 for ( i = 0; i < nn; i++ ) {
182 (*a)[n + i] = LDAP_STRDUP(s[i]);
183
184 if( (*a)[n + i] == NULL ) {
185 for( --i ; i >= 0 ; i-- ) {
186 LDAP_FREE( (*a)[n + i] );
187 (*a)[n + i] = NULL;
188 }
189 return -1;
190 }
191 }
192
193 (*a)[n + nn] = NULL;
194 return 0;
195 }
196
197 void
ldap_charray_free(char ** a)198 ldap_charray_free( char **a )
199 {
200 char **p;
201
202 if ( a == NULL ) {
203 return;
204 }
205
206 for ( p = a; *p != NULL; p++ ) {
207 if ( *p != NULL ) {
208 LDAP_FREE( *p );
209 }
210 }
211
212 LDAP_FREE( (char *) a );
213 }
214
215 int
ldap_charray_inlist(char ** a,char * s)216 ldap_charray_inlist(
217 char **a,
218 char *s
219 )
220 {
221 int i;
222
223 if( a == NULL ) return 0;
224
225 for ( i=0; a[i] != NULL; i++ ) {
226 if ( strcasecmp( s, a[i] ) == 0 ) {
227 return 1;
228 }
229 }
230
231 return 0;
232 }
233
234 char **
ldap_charray_dup(char ** a)235 ldap_charray_dup( char **a )
236 {
237 int i;
238 char **new;
239
240 for ( i = 0; a[i] != NULL; i++ )
241 ; /* NULL */
242
243 new = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) );
244
245 if( new == NULL ) {
246 return NULL;
247 }
248
249 for ( i = 0; a[i] != NULL; i++ ) {
250 new[i] = LDAP_STRDUP( a[i] );
251
252 if( new[i] == NULL ) {
253 for( --i ; i >= 0 ; i-- ) {
254 LDAP_FREE( new[i] );
255 }
256 LDAP_FREE( new );
257 return NULL;
258 }
259 }
260 new[i] = NULL;
261
262 return( new );
263 }
264
265 char **
ldap_str2charray(const char * str_in,const char * brkstr)266 ldap_str2charray( const char *str_in, const char *brkstr )
267 {
268 char **res;
269 char *str, *s;
270 int i;
271
272 /* protect the input string from strtok */
273 str = LDAP_STRDUP( str_in );
274 if( str == NULL ) {
275 return NULL;
276 }
277
278 i = 1;
279 for ( s = str; *s; s++ ) {
280 if ( ldap_utf8_strchr( brkstr, *s ) != NULL ) {
281 i++;
282 }
283 }
284
285 res = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) );
286
287 if( res == NULL ) {
288 LDAP_FREE( str );
289 return NULL;
290 }
291
292 i = 0;
293
294 for ( s = ldap_utf8_strtok( str, brkstr);
295 s != NULL;
296 s = ldap_utf8_strtok( NULL, brkstr) )
297 {
298 res[i] = LDAP_STRDUP( s );
299
300 if(res[i] == NULL) {
301 for( --i ; i >= 0 ; i-- ) {
302 LDAP_FREE( res[i] );
303 }
304 LDAP_FREE( res );
305 LDAP_FREE( str );
306 return NULL;
307 }
308
309 i++;
310 }
311
312 res[i] = NULL;
313
314 LDAP_FREE( str );
315 return( res );
316 }
317
ldap_charray2str(char ** a,const char * sep)318 char * ldap_charray2str( char **a, const char *sep )
319 {
320 char *s, **v, *p;
321 int len;
322 int slen;
323
324 if( sep == NULL ) sep = " ";
325
326 slen = strlen( sep );
327 len = 0;
328
329 for ( v = a; *v != NULL; v++ ) {
330 len += strlen( *v ) + slen;
331 }
332
333 if ( len == 0 ) {
334 return NULL;
335 }
336
337 /* trim extra sep len */
338 len -= slen;
339
340 s = LDAP_MALLOC ( len + 1 );
341
342 if ( s == NULL ) {
343 return NULL;
344 }
345
346 p = s;
347 for ( v = a; *v != NULL; v++ ) {
348 if ( v != a ) {
349 strncpy( p, sep, slen );
350 p += slen;
351 }
352
353 len = strlen( *v );
354 strncpy( p, *v, len );
355 p += len;
356 }
357
358 *p = '\0';
359 return s;
360 }
361
362
363
364 /* $OpenLDAP: pkg/ldap/libraries/libldap/url.c,v 1.64.2.5 2003/03/03 17:10:05 kurt Exp $ */
365 /*
366 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
367 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
368 */
369 /* Portions
370 * Copyright (c) 1996 Regents of the University of Michigan.
371 * All rights reserved.
372 *
373 * LIBLDAP url.c -- LDAP URL (RFC 2255) related routines
374 *
375 * LDAP URLs look like this:
376 * ldap[is]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
377 *
378 * where:
379 * attributes is a comma separated list
380 * scope is one of these three strings: base one sub (default=base)
381 * filter is an string-represented filter as in RFC 2254
382 *
383 * e.g., ldap://host:port/dc=com?o,cn?base?(o=openldap)?extension
384 *
385 * We also tolerate URLs that look like: <ldapurl> and <URL:ldapurl>
386 */
387
388 /* local functions */
389 static const char* skip_url_prefix LDAP_P((
390 const char *url,
391 int *enclosedp,
392 const char **scheme ));
393
394 int
ldap_is_ldap_url(LDAP_CONST char * url)395 ldap_is_ldap_url( LDAP_CONST char *url )
396 {
397 int enclosed;
398 const char * scheme;
399
400 if( url == NULL ) {
401 return 0;
402 }
403
404 if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
405 return 0;
406 }
407
408 return 1;
409 }
410
411
412 static const char*
skip_url_prefix(const char * url,int * enclosedp,const char ** scheme)413 skip_url_prefix(
414 const char *url,
415 int *enclosedp,
416 const char **scheme )
417 {
418 /*
419 * return non-zero if this looks like a LDAP URL; zero if not
420 * if non-zero returned, *urlp will be moved past "ldap://" part of URL
421 */
422 const char *p;
423
424 if ( url == NULL ) {
425 return( NULL );
426 }
427
428 p = url;
429
430 /* skip leading '<' (if any) */
431 if ( *p == '<' ) {
432 *enclosedp = 1;
433 ++p;
434 } else {
435 *enclosedp = 0;
436 }
437
438 /* skip leading "URL:" (if any) */
439 if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) {
440 p += LDAP_URL_URLCOLON_LEN;
441 }
442
443 /* check for "ldap://" prefix */
444 if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) {
445 /* skip over "ldap://" prefix and return success */
446 p += LDAP_URL_PREFIX_LEN;
447 *scheme = "ldap";
448 return( p );
449 }
450
451 /* check for "ldaps://" prefix */
452 if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) {
453 /* skip over "ldaps://" prefix and return success */
454 p += LDAPS_URL_PREFIX_LEN;
455 *scheme = "ldaps";
456 return( p );
457 }
458
459 /* check for "ldapi://" prefix */
460 if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) {
461 /* skip over "ldapi://" prefix and return success */
462 p += LDAPI_URL_PREFIX_LEN;
463 *scheme = "ldapi";
464 return( p );
465 }
466
467 #ifdef LDAP_CONNECTIONLESS
468 /* check for "cldap://" prefix */
469 if ( strncasecmp( p, LDAPC_URL_PREFIX, LDAPC_URL_PREFIX_LEN ) == 0 ) {
470 /* skip over "cldap://" prefix and return success */
471 p += LDAPC_URL_PREFIX_LEN;
472 *scheme = "cldap";
473 return( p );
474 }
475 #endif
476
477 return( NULL );
478 }
479
480
str2scope(const char * p)481 static int str2scope( const char *p )
482 {
483 if ( strcasecmp( p, "one" ) == 0 ) {
484 return LDAP_SCOPE_ONELEVEL;
485
486 } else if ( strcasecmp( p, "onetree" ) == 0 ) {
487 return LDAP_SCOPE_ONELEVEL;
488
489 } else if ( strcasecmp( p, "base" ) == 0 ) {
490 return LDAP_SCOPE_BASE;
491
492 } else if ( strcasecmp( p, "sub" ) == 0 ) {
493 return LDAP_SCOPE_SUBTREE;
494
495 } else if ( strcasecmp( p, "subtree" ) == 0 ) {
496 return LDAP_SCOPE_SUBTREE;
497 }
498
499 return( -1 );
500 }
501
502
503 int
ldap_url_parse_ext(LDAP_CONST char * url_in,LDAPURLDesc ** ludpp)504 ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
505 {
506 /*
507 * Pick apart the pieces of an LDAP URL.
508 */
509
510 LDAPURLDesc *ludp;
511 char *p, *q, *r;
512 int i, enclosed;
513 const char *scheme = NULL;
514 const char *url_tmp;
515 char *url;
516
517 if( url_in == NULL || ludpp == NULL ) {
518 return LDAP_URL_ERR_PARAM;
519 }
520
521 #ifndef LDAP_INT_IN_KERNEL
522 /* Global options may not be created yet
523 * We can't test if the global options are initialized
524 * because a call to LDAP_INT_GLOBAL_OPT() will try to allocate
525 * the options and cause infinite recursion
526 */
527 #ifdef NEW_LOGGING
528 LDAP_LOG ( OPERATION, ENTRY, "ldap_url_parse_ext(%s)\n", url_in, 0, 0 );
529 #else
530 Debug( LDAP_DEBUG_TRACE, "ldap_url_parse_ext(%s)\n", url_in, 0, 0 );
531 #endif
532 #endif
533
534 *ludpp = NULL; /* pessimistic */
535
536 url_tmp = skip_url_prefix( url_in, &enclosed, &scheme );
537
538 if ( url_tmp == NULL ) {
539 return LDAP_URL_ERR_BADSCHEME;
540 }
541
542 assert( scheme );
543
544 /* make working copy of the remainder of the URL */
545 url = LDAP_STRDUP( url_tmp );
546 if ( url == NULL ) {
547 return LDAP_URL_ERR_MEM;
548 }
549
550 if ( enclosed ) {
551 p = &url[strlen(url)-1];
552
553 if( *p != '>' ) {
554 LDAP_FREE( url );
555 return LDAP_URL_ERR_BADENCLOSURE;
556 }
557
558 *p = '\0';
559 }
560
561 /* allocate return struct */
562 ludp = (LDAPURLDesc *)LDAP_CALLOC( 1, sizeof( LDAPURLDesc ));
563
564 if ( ludp == NULL ) {
565 LDAP_FREE( url );
566 return LDAP_URL_ERR_MEM;
567 }
568
569 ludp->lud_next = NULL;
570 ludp->lud_host = NULL;
571 ludp->lud_port = 0;
572 ludp->lud_dn = NULL;
573 ludp->lud_attrs = NULL;
574 ludp->lud_filter = NULL;
575 ludp->lud_scope = LDAP_SCOPE_DEFAULT;
576 ludp->lud_filter = NULL;
577 ludp->lud_exts = NULL;
578
579 ludp->lud_scheme = LDAP_STRDUP( scheme );
580
581 if ( ludp->lud_scheme == NULL ) {
582 LDAP_FREE( url );
583 ldap_free_urldesc( ludp );
584 return LDAP_URL_ERR_MEM;
585 }
586
587 /* scan forward for '/' that marks end of hostport and begin. of dn */
588 p = strchr( url, '/' );
589
590 if( p != NULL ) {
591 /* terminate hostport; point to start of dn */
592 *p++ = '\0';
593 }
594
595 /* IPv6 syntax with [ip address]:port */
596 if ( *url == '[' ) {
597 r = strchr( url, ']' );
598 if ( r == NULL ) {
599 LDAP_FREE( url );
600 ldap_free_urldesc( ludp );
601 return LDAP_URL_ERR_BADURL;
602 }
603 *r++ = '\0';
604 q = strchr( r, ':' );
605 } else {
606 q = strchr( url, ':' );
607 }
608
609 if ( q != NULL ) {
610 *q++ = '\0';
611 ldap_pvt_hex_unescape( q );
612
613 if( *q == '\0' ) {
614 LDAP_FREE( url );
615 ldap_free_urldesc( ludp );
616 return LDAP_URL_ERR_BADURL;
617 }
618
619 ludp->lud_port = atoi( q );
620 }
621
622 ldap_pvt_hex_unescape( url );
623
624 /* If [ip address]:port syntax, url is [ip and we skip the [ */
625 ludp->lud_host = LDAP_STRDUP( url + ( *url == '[' ) );
626
627 if( ludp->lud_host == NULL ) {
628 LDAP_FREE( url );
629 ldap_free_urldesc( ludp );
630 return LDAP_URL_ERR_MEM;
631 }
632
633 /*
634 * Kludge. ldap://111.222.333.444:389??cn=abc,o=company
635 *
636 * On early Novell releases, search references/referrals were returned
637 * in this format, i.e., the dn was kind of in the scope position,
638 * but the required slash is missing. The whole thing is illegal syntax,
639 * but we need to account for it. Fortunately it can't be confused with
640 * anything real.
641 */
642 if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) {
643 q++;
644 /* ? immediately followed by question */
645 if( *q == '?') {
646 q++;
647 if( *q != '\0' ) {
648 /* parse dn part */
649 ldap_pvt_hex_unescape( q );
650 ludp->lud_dn = LDAP_STRDUP( q );
651 } else {
652 ludp->lud_dn = LDAP_STRDUP( "" );
653 }
654
655 if( ludp->lud_dn == NULL ) {
656 LDAP_FREE( url );
657 ldap_free_urldesc( ludp );
658 return LDAP_URL_ERR_MEM;
659 }
660 }
661 }
662
663 if( p == NULL ) {
664 LDAP_FREE( url );
665 *ludpp = ludp;
666 return LDAP_URL_SUCCESS;
667 }
668
669 /* scan forward for '?' that may marks end of dn */
670 q = strchr( p, '?' );
671
672 if( q != NULL ) {
673 /* terminate dn part */
674 *q++ = '\0';
675 }
676
677 if( *p != '\0' ) {
678 /* parse dn part */
679 ldap_pvt_hex_unescape( p );
680 ludp->lud_dn = LDAP_STRDUP( p );
681 } else {
682 ludp->lud_dn = LDAP_STRDUP( "" );
683 }
684
685 if( ludp->lud_dn == NULL ) {
686 LDAP_FREE( url );
687 ldap_free_urldesc( ludp );
688 return LDAP_URL_ERR_MEM;
689 }
690
691 if( q == NULL ) {
692 /* no more */
693 LDAP_FREE( url );
694 *ludpp = ludp;
695 return LDAP_URL_SUCCESS;
696 }
697
698 /* scan forward for '?' that may marks end of attributes */
699 p = q;
700 q = strchr( p, '?' );
701
702 if( q != NULL ) {
703 /* terminate attributes part */
704 *q++ = '\0';
705 }
706
707 if( *p != '\0' ) {
708 /* parse attributes */
709 ldap_pvt_hex_unescape( p );
710 ludp->lud_attrs = ldap_str2charray( p, "," );
711
712 if( ludp->lud_attrs == NULL ) {
713 LDAP_FREE( url );
714 ldap_free_urldesc( ludp );
715 return LDAP_URL_ERR_BADATTRS;
716 }
717 }
718
719 if ( q == NULL ) {
720 /* no more */
721 LDAP_FREE( url );
722 *ludpp = ludp;
723 return LDAP_URL_SUCCESS;
724 }
725
726 /* scan forward for '?' that may marks end of scope */
727 p = q;
728 q = strchr( p, '?' );
729
730 if( q != NULL ) {
731 /* terminate the scope part */
732 *q++ = '\0';
733 }
734
735 if( *p != '\0' ) {
736 /* parse the scope */
737 ldap_pvt_hex_unescape( p );
738 ludp->lud_scope = str2scope( p );
739
740 if( ludp->lud_scope == -1 ) {
741 LDAP_FREE( url );
742 ldap_free_urldesc( ludp );
743 return LDAP_URL_ERR_BADSCOPE;
744 }
745 }
746
747 if ( q == NULL ) {
748 /* no more */
749 LDAP_FREE( url );
750 *ludpp = ludp;
751 return LDAP_URL_SUCCESS;
752 }
753
754 /* scan forward for '?' that may marks end of filter */
755 p = q;
756 q = strchr( p, '?' );
757
758 if( q != NULL ) {
759 /* terminate the filter part */
760 *q++ = '\0';
761 }
762
763 if( *p != '\0' ) {
764 /* parse the filter */
765 ldap_pvt_hex_unescape( p );
766
767 if( ! *p ) {
768 /* missing filter */
769 LDAP_FREE( url );
770 ldap_free_urldesc( ludp );
771 return LDAP_URL_ERR_BADFILTER;
772 }
773
774 LDAP_FREE( ludp->lud_filter );
775 ludp->lud_filter = LDAP_STRDUP( p );
776
777 if( ludp->lud_filter == NULL ) {
778 LDAP_FREE( url );
779 ldap_free_urldesc( ludp );
780 return LDAP_URL_ERR_MEM;
781 }
782 }
783
784 if ( q == NULL ) {
785 /* no more */
786 LDAP_FREE( url );
787 *ludpp = ludp;
788 return LDAP_URL_SUCCESS;
789 }
790
791 /* scan forward for '?' that may marks end of extensions */
792 p = q;
793 q = strchr( p, '?' );
794
795 if( q != NULL ) {
796 /* extra '?' */
797 LDAP_FREE( url );
798 ldap_free_urldesc( ludp );
799 return LDAP_URL_ERR_BADURL;
800 }
801
802 /* parse the extensions */
803 ludp->lud_exts = ldap_str2charray( p, "," );
804
805 if( ludp->lud_exts == NULL ) {
806 LDAP_FREE( url );
807 ldap_free_urldesc( ludp );
808 return LDAP_URL_ERR_BADEXTS;
809 }
810
811 for( i=0; ludp->lud_exts[i] != NULL; i++ ) {
812 ldap_pvt_hex_unescape( ludp->lud_exts[i] );
813
814 if( *ludp->lud_exts[i] == '!' ) {
815 /* count the number of critical extensions */
816 ludp->lud_crit_exts++;
817 }
818 }
819
820 if( i == 0 ) {
821 /* must have 1 or more */
822 LDAP_FREE( url );
823 ldap_free_urldesc( ludp );
824 return LDAP_URL_ERR_BADEXTS;
825 }
826
827 /* no more */
828 *ludpp = ludp;
829 LDAP_FREE( url );
830 return LDAP_URL_SUCCESS;
831 }
832
833 int
ldap_url_parse(LDAP_CONST char * url_in,LDAPURLDesc ** ludpp)834 ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
835 {
836 int rc = ldap_url_parse_ext( url_in, ludpp );
837
838 if( rc != LDAP_URL_SUCCESS ) {
839 return rc;
840 }
841
842 if ((*ludpp)->lud_scope == LDAP_SCOPE_DEFAULT) {
843 (*ludpp)->lud_scope = LDAP_SCOPE_BASE;
844 }
845
846 if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') {
847 LDAP_FREE( (*ludpp)->lud_host );
848 (*ludpp)->lud_host = NULL;
849 }
850
851 if ((*ludpp)->lud_port == 0) {
852 if( strcmp((*ludpp)->lud_scheme, "ldap") == 0 ) {
853 (*ludpp)->lud_port = LDAP_PORT;
854 #ifdef LDAP_CONNECTIONLESS
855 } else if( strcmp((*ludpp)->lud_scheme, "cldap") == 0 ) {
856 (*ludpp)->lud_port = LDAP_PORT;
857 #endif
858 } else if( strcmp((*ludpp)->lud_scheme, "ldaps") == 0 ) {
859 (*ludpp)->lud_port = LDAPS_PORT;
860 }
861 }
862
863 return rc;
864 }
865
866
867 void
ldap_free_urldesc(LDAPURLDesc * ludp)868 ldap_free_urldesc( LDAPURLDesc *ludp )
869 {
870 if ( ludp == NULL ) {
871 return;
872 }
873
874 if ( ludp->lud_scheme != NULL ) {
875 LDAP_FREE( ludp->lud_scheme );
876 }
877
878 if ( ludp->lud_host != NULL ) {
879 LDAP_FREE( ludp->lud_host );
880 }
881
882 if ( ludp->lud_dn != NULL ) {
883 LDAP_FREE( ludp->lud_dn );
884 }
885
886 if ( ludp->lud_filter != NULL ) {
887 LDAP_FREE( ludp->lud_filter);
888 }
889
890 if ( ludp->lud_attrs != NULL ) {
891 LDAP_VFREE( ludp->lud_attrs );
892 }
893
894 if ( ludp->lud_exts != NULL ) {
895 LDAP_VFREE( ludp->lud_exts );
896 }
897
898 LDAP_FREE( ludp );
899 }
900
901
902 static int
ldap_int_unhex(int c)903 ldap_int_unhex( int c )
904 {
905 return( c >= '0' && c <= '9' ? c - '0'
906 : c >= 'A' && c <= 'F' ? c - 'A' + 10
907 : c - 'a' + 10 );
908 }
909
910 void
ldap_pvt_hex_unescape(char * s)911 ldap_pvt_hex_unescape( char *s )
912 {
913 /*
914 * Remove URL hex escapes from s... done in place. The basic concept for
915 * this routine is borrowed from the WWW library HTUnEscape() routine.
916 */
917 char *p;
918
919 for ( p = s; *s != '\0'; ++s ) {
920 if ( *s == '%' ) {
921 if ( *++s == '\0' ) {
922 break;
923 }
924 *p = ldap_int_unhex( *s ) << 4;
925 if ( *++s == '\0' ) {
926 break;
927 }
928 *p++ += ldap_int_unhex( *s );
929 } else {
930 *p++ = *s;
931 }
932 }
933
934 *p = '\0';
935 }
936