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