1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
3*0Sstevel@tonic-gate * Use is subject to license terms.
4*0Sstevel@tonic-gate */
5*0Sstevel@tonic-gate
6*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
7*0Sstevel@tonic-gate
8*0Sstevel@tonic-gate /*
9*0Sstevel@tonic-gate * Copyright (c) 1996 Regents of the University of Michigan.
10*0Sstevel@tonic-gate * All rights reserved.
11*0Sstevel@tonic-gate *
12*0Sstevel@tonic-gate * LIBLDAP url.c -- LDAP URL related routines
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * LDAP URLs look like this:
15*0Sstevel@tonic-gate * l d a p : / / hostport / dn [ ? attributes [ ? scope [ ? filter [ ? extensions ] ] ] ]
16*0Sstevel@tonic-gate *
17*0Sstevel@tonic-gate * where:
18*0Sstevel@tonic-gate * attributes is a comma separated list
19*0Sstevel@tonic-gate * scope is one of these three strings: base one sub (default=base)
20*0Sstevel@tonic-gate * filter is an string-represented filter as in RFC 1558
21*0Sstevel@tonic-gate * extensions is a comma separated list of extension
22*0Sstevel@tonic-gate * and extension is like this: [ ! ] oid/x-oid [ = value ]
23*0Sstevel@tonic-gate *
24*0Sstevel@tonic-gate * e.g., ldap://ldap.itd.umich.edu/c=US?o,description?one?o=umich
25*0Sstevel@tonic-gate *
26*0Sstevel@tonic-gate * We also tolerate URLs that look like: <ldapurl> and <URL:ldapurl>
27*0Sstevel@tonic-gate */
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate #ifndef lint
30*0Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1996 Regents of the University of Michigan.\nAll rights reserved.\n";
31*0Sstevel@tonic-gate #endif
32*0Sstevel@tonic-gate
33*0Sstevel@tonic-gate #include <stdio.h>
34*0Sstevel@tonic-gate #include <string.h>
35*0Sstevel@tonic-gate #include <ctype.h>
36*0Sstevel@tonic-gate
37*0Sstevel@tonic-gate #ifdef MACOS
38*0Sstevel@tonic-gate #include <stdlib.h>
39*0Sstevel@tonic-gate #include "macos.h"
40*0Sstevel@tonic-gate #endif /* MACOS */
41*0Sstevel@tonic-gate
42*0Sstevel@tonic-gate #if defined( DOS ) || defined( _WIN32 )
43*0Sstevel@tonic-gate #include <stdlib.h>
44*0Sstevel@tonic-gate #include <malloc.h>
45*0Sstevel@tonic-gate #include "msdos.h"
46*0Sstevel@tonic-gate #endif /* DOS || _WIN32 */
47*0Sstevel@tonic-gate
48*0Sstevel@tonic-gate #if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 )
49*0Sstevel@tonic-gate #include <sys/time.h>
50*0Sstevel@tonic-gate #include <sys/types.h>
51*0Sstevel@tonic-gate #include <sys/socket.h>
52*0Sstevel@tonic-gate #endif /* !MACOS && !DOS && !_WIN32 */
53*0Sstevel@tonic-gate
54*0Sstevel@tonic-gate #include "lber.h"
55*0Sstevel@tonic-gate #include "ldap.h"
56*0Sstevel@tonic-gate #include "ldap-private.h"
57*0Sstevel@tonic-gate #include "ldap-int.h"
58*0Sstevel@tonic-gate
59*0Sstevel@tonic-gate
60*0Sstevel@tonic-gate #ifdef NEEDPROTOS
61*0Sstevel@tonic-gate static int skip_url_prefix( char **urlp, int *enclosedp );
62*0Sstevel@tonic-gate static void hex_unescape( char *s );
63*0Sstevel@tonic-gate static int unhex( char c );
64*0Sstevel@tonic-gate #else /* NEEDPROTOS */
65*0Sstevel@tonic-gate static int skip_url_prefix();
66*0Sstevel@tonic-gate static void hex_unescape();
67*0Sstevel@tonic-gate static int unhex();
68*0Sstevel@tonic-gate #endif /* NEEDPROTOS */
69*0Sstevel@tonic-gate
70*0Sstevel@tonic-gate
71*0Sstevel@tonic-gate int
ldap_is_ldap_url(char * url)72*0Sstevel@tonic-gate ldap_is_ldap_url( char *url )
73*0Sstevel@tonic-gate {
74*0Sstevel@tonic-gate int enclosed;
75*0Sstevel@tonic-gate
76*0Sstevel@tonic-gate return( url != NULL && skip_url_prefix( &url, &enclosed ));
77*0Sstevel@tonic-gate }
78*0Sstevel@tonic-gate
79*0Sstevel@tonic-gate
80*0Sstevel@tonic-gate static int
skip_url_prefix(char ** urlp,int * enclosedp)81*0Sstevel@tonic-gate skip_url_prefix( char **urlp, int *enclosedp )
82*0Sstevel@tonic-gate {
83*0Sstevel@tonic-gate /*
84*0Sstevel@tonic-gate * return non-zero if this looks like a LDAP URL; zero if not
85*0Sstevel@tonic-gate * if non-zero returned, *urlp will be moved past "ldap://" part of URL
86*0Sstevel@tonic-gate */
87*0Sstevel@tonic-gate if ( *urlp == NULL ) {
88*0Sstevel@tonic-gate return( 0 );
89*0Sstevel@tonic-gate }
90*0Sstevel@tonic-gate
91*0Sstevel@tonic-gate /* skip leading '<' (if any) */
92*0Sstevel@tonic-gate if ( **urlp == '<' ) {
93*0Sstevel@tonic-gate *enclosedp = 1;
94*0Sstevel@tonic-gate ++*urlp;
95*0Sstevel@tonic-gate } else {
96*0Sstevel@tonic-gate *enclosedp = 0;
97*0Sstevel@tonic-gate }
98*0Sstevel@tonic-gate
99*0Sstevel@tonic-gate /* skip leading "URL:" (if any) */
100*0Sstevel@tonic-gate if ( strlen( *urlp ) >= LDAP_URL_URLCOLON_LEN && strncasecmp(
101*0Sstevel@tonic-gate *urlp, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) {
102*0Sstevel@tonic-gate *urlp += LDAP_URL_URLCOLON_LEN;
103*0Sstevel@tonic-gate }
104*0Sstevel@tonic-gate
105*0Sstevel@tonic-gate /* check for missing "ldap://" prefix */
106*0Sstevel@tonic-gate if ( strlen( *urlp ) < LDAP_URL_PREFIX_LEN ||
107*0Sstevel@tonic-gate strncasecmp( *urlp, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) != 0 ) {
108*0Sstevel@tonic-gate return( 0 );
109*0Sstevel@tonic-gate }
110*0Sstevel@tonic-gate
111*0Sstevel@tonic-gate /* skip over "ldap://" prefix and return success */
112*0Sstevel@tonic-gate *urlp += LDAP_URL_PREFIX_LEN;
113*0Sstevel@tonic-gate return( 1 );
114*0Sstevel@tonic-gate }
115*0Sstevel@tonic-gate
ldap_url_extension_parse(char * exts,LDAPURLExt *** lueppp)116*0Sstevel@tonic-gate int ldap_url_extension_parse( char *exts, LDAPURLExt *** lueppp)
117*0Sstevel@tonic-gate {
118*0Sstevel@tonic-gate /* Pick apart the pieces of an LDAP URL Extensions */
119*0Sstevel@tonic-gate /* No copy of exts is made, LDAPURLExt's points to exts string */
120*0Sstevel@tonic-gate LDAPURLExt ** lues;
121*0Sstevel@tonic-gate LDAPURLExt *luep;
122*0Sstevel@tonic-gate int i = 0;
123*0Sstevel@tonic-gate char *p = exts;
124*0Sstevel@tonic-gate char *ptr, *ptr2;
125*0Sstevel@tonic-gate
126*0Sstevel@tonic-gate *lueppp = NULL;
127*0Sstevel@tonic-gate
128*0Sstevel@tonic-gate /* Count the number of , in extensions */
129*0Sstevel@tonic-gate while ( (p = strchr (p, ',')) != NULL){
130*0Sstevel@tonic-gate i++;
131*0Sstevel@tonic-gate }
132*0Sstevel@tonic-gate /* There are at most i+1 extensions */
133*0Sstevel@tonic-gate if ((lues = (LDAPURLExt **)calloc(i+2, sizeof(LDAPURLExt *))) == NULL){
134*0Sstevel@tonic-gate return (LDAP_URL_ERR_MEM);
135*0Sstevel@tonic-gate }
136*0Sstevel@tonic-gate
137*0Sstevel@tonic-gate p = exts;
138*0Sstevel@tonic-gate i = 0;
139*0Sstevel@tonic-gate
140*0Sstevel@tonic-gate while ( p ) {
141*0Sstevel@tonic-gate if ((ptr = strchr(p, ',')) != NULL)
142*0Sstevel@tonic-gate *ptr++ = '\0';
143*0Sstevel@tonic-gate else
144*0Sstevel@tonic-gate ptr = NULL;
145*0Sstevel@tonic-gate
146*0Sstevel@tonic-gate if ((luep = (LDAPURLExt *)calloc(1, sizeof(LDAPURLExt))) == NULL){
147*0Sstevel@tonic-gate ldap_free_urlexts(lues);
148*0Sstevel@tonic-gate return (LDAP_URL_ERR_MEM);
149*0Sstevel@tonic-gate }
150*0Sstevel@tonic-gate lues[i] = luep;
151*0Sstevel@tonic-gate
152*0Sstevel@tonic-gate if (*p == '!'){
153*0Sstevel@tonic-gate luep->lue_iscritical = 1;
154*0Sstevel@tonic-gate p++;
155*0Sstevel@tonic-gate }
156*0Sstevel@tonic-gate luep->lue_type = p;
157*0Sstevel@tonic-gate
158*0Sstevel@tonic-gate if (( ptr2 = strchr(p, '=')) != NULL) {
159*0Sstevel@tonic-gate *ptr2++ = '\0';
160*0Sstevel@tonic-gate luep->lue_value = ptr2;
161*0Sstevel@tonic-gate hex_unescape(ptr2);
162*0Sstevel@tonic-gate }
163*0Sstevel@tonic-gate
164*0Sstevel@tonic-gate i++;
165*0Sstevel@tonic-gate p = ptr;
166*0Sstevel@tonic-gate }
167*0Sstevel@tonic-gate *lueppp = lues;
168*0Sstevel@tonic-gate
169*0Sstevel@tonic-gate return( 0 );
170*0Sstevel@tonic-gate }
171*0Sstevel@tonic-gate
172*0Sstevel@tonic-gate
173*0Sstevel@tonic-gate int
ldap_url_parse(char * url,LDAPURLDesc ** ludpp)174*0Sstevel@tonic-gate ldap_url_parse( char *url, LDAPURLDesc **ludpp )
175*0Sstevel@tonic-gate {
176*0Sstevel@tonic-gate /*
177*0Sstevel@tonic-gate * Pick apart the pieces of an LDAP URL.
178*0Sstevel@tonic-gate */
179*0Sstevel@tonic-gate
180*0Sstevel@tonic-gate LDAPURLDesc *ludp;
181*0Sstevel@tonic-gate char *attrs = NULL;
182*0Sstevel@tonic-gate char *p = NULL;
183*0Sstevel@tonic-gate char *q = NULL;
184*0Sstevel@tonic-gate char *x = NULL;
185*0Sstevel@tonic-gate int enclosed, i, nattrs, errcode;
186*0Sstevel@tonic-gate
187*0Sstevel@tonic-gate Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 262, "ldap_url_parse(%s)\n"), url, 0, 0 );
188*0Sstevel@tonic-gate
189*0Sstevel@tonic-gate *ludpp = NULL; /* pessimistic */
190*0Sstevel@tonic-gate
191*0Sstevel@tonic-gate if ( !skip_url_prefix( &url, &enclosed )) {
192*0Sstevel@tonic-gate return( LDAP_URL_ERR_NOTLDAP );
193*0Sstevel@tonic-gate }
194*0Sstevel@tonic-gate
195*0Sstevel@tonic-gate /* allocate return struct */
196*0Sstevel@tonic-gate if (( ludp = (LDAPURLDesc *)calloc( 1, sizeof( LDAPURLDesc )))
197*0Sstevel@tonic-gate == NULLLDAPURLDESC ) {
198*0Sstevel@tonic-gate return( LDAP_URL_ERR_MEM );
199*0Sstevel@tonic-gate }
200*0Sstevel@tonic-gate
201*0Sstevel@tonic-gate ludp->lud_port = LDAP_PORT;
202*0Sstevel@tonic-gate
203*0Sstevel@tonic-gate /* make working copy of the remainder of the URL */
204*0Sstevel@tonic-gate if (( url = strdup( url )) == NULL ) {
205*0Sstevel@tonic-gate ldap_free_urldesc( ludp );
206*0Sstevel@tonic-gate return( LDAP_URL_ERR_MEM );
207*0Sstevel@tonic-gate }
208*0Sstevel@tonic-gate
209*0Sstevel@tonic-gate if ( enclosed && *((p = url + strlen( url ) - 1)) == '>' ) {
210*0Sstevel@tonic-gate *p = '\0';
211*0Sstevel@tonic-gate }
212*0Sstevel@tonic-gate
213*0Sstevel@tonic-gate /* set defaults */
214*0Sstevel@tonic-gate /* LP By default don't set them... Then we can check if they are present or not in URL */
215*0Sstevel@tonic-gate ludp->lud_scope = LDAP_SCOPE_UNKNOWN;
216*0Sstevel@tonic-gate ludp->lud_filter = NULL;
217*0Sstevel@tonic-gate
218*0Sstevel@tonic-gate
219*0Sstevel@tonic-gate /* lud_string is the only malloc'd string space we use */
220*0Sstevel@tonic-gate ludp->lud_string = url;
221*0Sstevel@tonic-gate
222*0Sstevel@tonic-gate /* scan forward for '/' that marks end of hostport and begin. of dn */
223*0Sstevel@tonic-gate if (( ludp->lud_dn = strchr( url, '/' )) != NULL ) {
224*0Sstevel@tonic-gate *ludp->lud_dn++ = '\0';
225*0Sstevel@tonic-gate }
226*0Sstevel@tonic-gate
227*0Sstevel@tonic-gate /* terminate hostport; point to start of dn */
228*0Sstevel@tonic-gate
229*0Sstevel@tonic-gate if (( p = strchr( url, ':' )) != NULL ) {
230*0Sstevel@tonic-gate *p++ = '\0';
231*0Sstevel@tonic-gate ludp->lud_port = atoi( p );
232*0Sstevel@tonic-gate }
233*0Sstevel@tonic-gate
234*0Sstevel@tonic-gate if ( *url == '\0' ) {
235*0Sstevel@tonic-gate ludp->lud_host = NULL;
236*0Sstevel@tonic-gate } else {
237*0Sstevel@tonic-gate ludp->lud_host = url;
238*0Sstevel@tonic-gate hex_unescape( ludp->lud_host );
239*0Sstevel@tonic-gate }
240*0Sstevel@tonic-gate
241*0Sstevel@tonic-gate if (ludp->lud_dn != NULL){
242*0Sstevel@tonic-gate /* scan for '?' that marks end of dn and beginning of attributes */
243*0Sstevel@tonic-gate if (( attrs = strchr( ludp->lud_dn, '?' )) != NULL ) {
244*0Sstevel@tonic-gate /* terminate dn; point to start of attrs. */
245*0Sstevel@tonic-gate *attrs++ = '\0';
246*0Sstevel@tonic-gate
247*0Sstevel@tonic-gate /* scan for '?' that marks end of attrs and begin. of scope */
248*0Sstevel@tonic-gate if (( p = strchr( attrs, '?' )) != NULL ) {
249*0Sstevel@tonic-gate /*
250*0Sstevel@tonic-gate * terminate attrs; point to start of scope and scan for
251*0Sstevel@tonic-gate * '?' that marks end of scope and begin. of filter
252*0Sstevel@tonic-gate */
253*0Sstevel@tonic-gate *p++ = '\0';
254*0Sstevel@tonic-gate
255*0Sstevel@tonic-gate if (( q = strchr( p, '?' )) != NULL ) {
256*0Sstevel@tonic-gate /* terminate scope; point to start of filter */
257*0Sstevel@tonic-gate *q++ = '\0';
258*0Sstevel@tonic-gate
259*0Sstevel@tonic-gate if (( x = strchr(q, '?')) != NULL ) {
260*0Sstevel@tonic-gate /* terminate filter; point to start of extension */
261*0Sstevel@tonic-gate *x++ = '\0';
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gate if (*x != '\0'){
264*0Sstevel@tonic-gate /* parse extensions */
265*0Sstevel@tonic-gate }
266*0Sstevel@tonic-gate }
267*0Sstevel@tonic-gate
268*0Sstevel@tonic-gate if ( *q != '\0' ) {
269*0Sstevel@tonic-gate ludp->lud_filter = q;
270*0Sstevel@tonic-gate hex_unescape( ludp->lud_filter );
271*0Sstevel@tonic-gate }
272*0Sstevel@tonic-gate }
273*0Sstevel@tonic-gate
274*0Sstevel@tonic-gate if ( strcasecmp( p, "one" ) == 0 ) {
275*0Sstevel@tonic-gate ludp->lud_scope = LDAP_SCOPE_ONELEVEL;
276*0Sstevel@tonic-gate } else if ( strcasecmp( p, "base" ) == 0 ) {
277*0Sstevel@tonic-gate ludp->lud_scope = LDAP_SCOPE_BASE;
278*0Sstevel@tonic-gate } else if ( strcasecmp( p, "sub" ) == 0 ) {
279*0Sstevel@tonic-gate ludp->lud_scope = LDAP_SCOPE_SUBTREE;
280*0Sstevel@tonic-gate } else if ( *p != '\0' ) {
281*0Sstevel@tonic-gate ldap_free_urldesc( ludp );
282*0Sstevel@tonic-gate return( LDAP_URL_ERR_BADSCOPE );
283*0Sstevel@tonic-gate }
284*0Sstevel@tonic-gate }
285*0Sstevel@tonic-gate }
286*0Sstevel@tonic-gate if ( *ludp->lud_dn == '\0' ) {
287*0Sstevel@tonic-gate ludp->lud_dn = NULL;
288*0Sstevel@tonic-gate } else {
289*0Sstevel@tonic-gate hex_unescape( ludp->lud_dn );
290*0Sstevel@tonic-gate }
291*0Sstevel@tonic-gate
292*0Sstevel@tonic-gate /*
293*0Sstevel@tonic-gate * if attrs list was included, turn it into a null-terminated array
294*0Sstevel@tonic-gate */
295*0Sstevel@tonic-gate if ( attrs != NULL && *attrs != '\0' ) {
296*0Sstevel@tonic-gate for ( nattrs = 1, p = attrs; *p != '\0'; ++p ) {
297*0Sstevel@tonic-gate if ( *p == ',' ) {
298*0Sstevel@tonic-gate ++nattrs;
299*0Sstevel@tonic-gate }
300*0Sstevel@tonic-gate }
301*0Sstevel@tonic-gate
302*0Sstevel@tonic-gate if (( ludp->lud_attrs = (char **)calloc( nattrs + 1,
303*0Sstevel@tonic-gate sizeof( char * ))) == NULL ) {
304*0Sstevel@tonic-gate ldap_free_urldesc( ludp );
305*0Sstevel@tonic-gate return( LDAP_URL_ERR_MEM );
306*0Sstevel@tonic-gate }
307*0Sstevel@tonic-gate
308*0Sstevel@tonic-gate for ( i = 0, p = attrs; i < nattrs; ++i ) {
309*0Sstevel@tonic-gate ludp->lud_attrs[ i ] = p;
310*0Sstevel@tonic-gate if (( p = strchr( p, ',' )) != NULL ) {
311*0Sstevel@tonic-gate *p++ ='\0';
312*0Sstevel@tonic-gate }
313*0Sstevel@tonic-gate hex_unescape( ludp->lud_attrs[ i ] );
314*0Sstevel@tonic-gate }
315*0Sstevel@tonic-gate }
316*0Sstevel@tonic-gate
317*0Sstevel@tonic-gate if (x != NULL && *x != '\0'){
318*0Sstevel@tonic-gate if (errcode = ldap_url_extension_parse(x, &ludp->lud_extensions)){
319*0Sstevel@tonic-gate ldap_free_urldesc(ludp);
320*0Sstevel@tonic-gate return ( errcode );
321*0Sstevel@tonic-gate }
322*0Sstevel@tonic-gate }
323*0Sstevel@tonic-gate }
324*0Sstevel@tonic-gate
325*0Sstevel@tonic-gate *ludpp = ludp;
326*0Sstevel@tonic-gate
327*0Sstevel@tonic-gate return( 0 );
328*0Sstevel@tonic-gate }
329*0Sstevel@tonic-gate
ldap_free_urlexts(LDAPURLExt ** lues)330*0Sstevel@tonic-gate void ldap_free_urlexts( LDAPURLExt ** lues)
331*0Sstevel@tonic-gate {
332*0Sstevel@tonic-gate int i;
333*0Sstevel@tonic-gate for (i = 0; lues[i] != NULL; i++){
334*0Sstevel@tonic-gate free(lues[i]);
335*0Sstevel@tonic-gate }
336*0Sstevel@tonic-gate free(lues);
337*0Sstevel@tonic-gate }
338*0Sstevel@tonic-gate
339*0Sstevel@tonic-gate
340*0Sstevel@tonic-gate void
ldap_free_urldesc(LDAPURLDesc * ludp)341*0Sstevel@tonic-gate ldap_free_urldesc( LDAPURLDesc *ludp )
342*0Sstevel@tonic-gate {
343*0Sstevel@tonic-gate if ( ludp != NULLLDAPURLDESC ) {
344*0Sstevel@tonic-gate if ( ludp->lud_string != NULL ) {
345*0Sstevel@tonic-gate free( ludp->lud_string );
346*0Sstevel@tonic-gate }
347*0Sstevel@tonic-gate if ( ludp->lud_attrs != NULL ) {
348*0Sstevel@tonic-gate free( ludp->lud_attrs );
349*0Sstevel@tonic-gate }
350*0Sstevel@tonic-gate if (ludp->lud_extensions != NULL) {
351*0Sstevel@tonic-gate ldap_free_urlexts(ludp->lud_extensions);
352*0Sstevel@tonic-gate }
353*0Sstevel@tonic-gate free( ludp );
354*0Sstevel@tonic-gate }
355*0Sstevel@tonic-gate }
356*0Sstevel@tonic-gate
357*0Sstevel@tonic-gate
358*0Sstevel@tonic-gate
359*0Sstevel@tonic-gate int
ldap_url_search(LDAP * ld,char * url,int attrsonly)360*0Sstevel@tonic-gate ldap_url_search( LDAP *ld, char *url, int attrsonly )
361*0Sstevel@tonic-gate {
362*0Sstevel@tonic-gate int err;
363*0Sstevel@tonic-gate LDAPURLDesc *ludp;
364*0Sstevel@tonic-gate BerElement *ber;
365*0Sstevel@tonic-gate LDAPServer *srv = NULL;
366*0Sstevel@tonic-gate
367*0Sstevel@tonic-gate #ifdef _REENTRANT
368*0Sstevel@tonic-gate LOCK_LDAP(ld);
369*0Sstevel@tonic-gate #endif
370*0Sstevel@tonic-gate if ( ldap_url_parse( url, &ludp ) != 0 ) {
371*0Sstevel@tonic-gate ld->ld_errno = LDAP_PARAM_ERROR;
372*0Sstevel@tonic-gate #ifdef _REENTRANT
373*0Sstevel@tonic-gate UNLOCK_LDAP(ld);
374*0Sstevel@tonic-gate #endif
375*0Sstevel@tonic-gate return( -1 );
376*0Sstevel@tonic-gate }
377*0Sstevel@tonic-gate
378*0Sstevel@tonic-gate if (( ber = ldap_build_search_req( ld, ludp->lud_dn,
379*0Sstevel@tonic-gate ludp->lud_scope == LDAP_SCOPE_UNKNOWN ? LDAP_SCOPE_BASE : ludp->lud_scope,
380*0Sstevel@tonic-gate ludp->lud_filter ? ludp->lud_filter : "(objectclass=*)",
381*0Sstevel@tonic-gate ludp->lud_attrs, attrsonly, NULL, NULL, -1 )) == NULLBER ) {
382*0Sstevel@tonic-gate #ifdef _REENTRANT
383*0Sstevel@tonic-gate UNLOCK_LDAP(ld);
384*0Sstevel@tonic-gate #endif
385*0Sstevel@tonic-gate return( -1 );
386*0Sstevel@tonic-gate }
387*0Sstevel@tonic-gate
388*0Sstevel@tonic-gate err = 0;
389*0Sstevel@tonic-gate
390*0Sstevel@tonic-gate if ( ludp->lud_host != NULL || ludp->lud_port != 0 ) {
391*0Sstevel@tonic-gate if (( srv = (LDAPServer *)calloc( 1, sizeof( LDAPServer )))
392*0Sstevel@tonic-gate == NULL || ( srv->lsrv_host = strdup( ludp->lud_host ==
393*0Sstevel@tonic-gate NULL ? ld->ld_defhost : ludp->lud_host )) == NULL ) {
394*0Sstevel@tonic-gate if ( srv != NULL ) {
395*0Sstevel@tonic-gate free( srv );
396*0Sstevel@tonic-gate }
397*0Sstevel@tonic-gate ld->ld_errno = LDAP_NO_MEMORY;
398*0Sstevel@tonic-gate err = -1;
399*0Sstevel@tonic-gate } else {
400*0Sstevel@tonic-gate if ( ludp->lud_port == 0 ) {
401*0Sstevel@tonic-gate srv->lsrv_port = LDAP_PORT;
402*0Sstevel@tonic-gate } else {
403*0Sstevel@tonic-gate srv->lsrv_port = ludp->lud_port;
404*0Sstevel@tonic-gate }
405*0Sstevel@tonic-gate }
406*0Sstevel@tonic-gate }
407*0Sstevel@tonic-gate
408*0Sstevel@tonic-gate if ( err != 0 ) {
409*0Sstevel@tonic-gate ber_free( ber, 1 );
410*0Sstevel@tonic-gate } else {
411*0Sstevel@tonic-gate err = send_server_request( ld, ber, ld->ld_msgid, NULL, srv, NULL, 1 );
412*0Sstevel@tonic-gate }
413*0Sstevel@tonic-gate
414*0Sstevel@tonic-gate ldap_free_urldesc( ludp );
415*0Sstevel@tonic-gate
416*0Sstevel@tonic-gate #ifdef _REENTRANT
417*0Sstevel@tonic-gate UNLOCK_LDAP(ld);
418*0Sstevel@tonic-gate #endif
419*0Sstevel@tonic-gate return( err );
420*0Sstevel@tonic-gate }
421*0Sstevel@tonic-gate
422*0Sstevel@tonic-gate
423*0Sstevel@tonic-gate int
ldap_url_search_st(LDAP * ld,char * url,int attrsonly,struct timeval * timeout,LDAPMessage ** res)424*0Sstevel@tonic-gate ldap_url_search_st( LDAP *ld, char *url, int attrsonly,
425*0Sstevel@tonic-gate struct timeval *timeout, LDAPMessage **res )
426*0Sstevel@tonic-gate {
427*0Sstevel@tonic-gate int msgid;
428*0Sstevel@tonic-gate int retcode = LDAP_SUCCESS;
429*0Sstevel@tonic-gate
430*0Sstevel@tonic-gate if (( msgid = ldap_url_search( ld, url, attrsonly )) == -1 ) {
431*0Sstevel@tonic-gate return( ld->ld_errno );
432*0Sstevel@tonic-gate }
433*0Sstevel@tonic-gate
434*0Sstevel@tonic-gate if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 ) {
435*0Sstevel@tonic-gate return( ld->ld_errno );
436*0Sstevel@tonic-gate }
437*0Sstevel@tonic-gate
438*0Sstevel@tonic-gate if ( ld->ld_errno == LDAP_TIMEOUT ) {
439*0Sstevel@tonic-gate (void) ldap_abandon( ld, msgid );
440*0Sstevel@tonic-gate ld->ld_errno = LDAP_TIMEOUT;
441*0Sstevel@tonic-gate return( ld->ld_errno );
442*0Sstevel@tonic-gate }
443*0Sstevel@tonic-gate
444*0Sstevel@tonic-gate #ifdef _REENTRANT
445*0Sstevel@tonic-gate LOCK_LDAP(ld);
446*0Sstevel@tonic-gate #endif
447*0Sstevel@tonic-gate retcode = ldap_parse_result(ld, *res, &ld->ld_errno, &ld->ld_matched, &ld->ld_error,
448*0Sstevel@tonic-gate &ld->ld_referrals, &ld->ld_ret_ctrls, 0);
449*0Sstevel@tonic-gate if (retcode == LDAP_SUCCESS)
450*0Sstevel@tonic-gate retcode = ld->ld_errno;
451*0Sstevel@tonic-gate #ifdef _REENTRANT
452*0Sstevel@tonic-gate UNLOCK_LDAP(ld);
453*0Sstevel@tonic-gate #endif
454*0Sstevel@tonic-gate
455*0Sstevel@tonic-gate return (retcode);
456*0Sstevel@tonic-gate }
457*0Sstevel@tonic-gate
458*0Sstevel@tonic-gate
459*0Sstevel@tonic-gate int
ldap_url_search_s(LDAP * ld,char * url,int attrsonly,LDAPMessage ** res)460*0Sstevel@tonic-gate ldap_url_search_s( LDAP *ld, char *url, int attrsonly, LDAPMessage **res )
461*0Sstevel@tonic-gate {
462*0Sstevel@tonic-gate int msgid;
463*0Sstevel@tonic-gate int retcode = LDAP_SUCCESS;
464*0Sstevel@tonic-gate
465*0Sstevel@tonic-gate if (( msgid = ldap_url_search( ld, url, attrsonly )) == -1 ) {
466*0Sstevel@tonic-gate return( ld->ld_errno );
467*0Sstevel@tonic-gate }
468*0Sstevel@tonic-gate
469*0Sstevel@tonic-gate if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, res ) == -1 ) {
470*0Sstevel@tonic-gate return( ld->ld_errno );
471*0Sstevel@tonic-gate }
472*0Sstevel@tonic-gate
473*0Sstevel@tonic-gate #ifdef _REENTRANT
474*0Sstevel@tonic-gate LOCK_LDAP(ld);
475*0Sstevel@tonic-gate #endif
476*0Sstevel@tonic-gate retcode = ldap_parse_result(ld, *res, &ld->ld_errno, &ld->ld_matched, &ld->ld_error,
477*0Sstevel@tonic-gate &ld->ld_referrals, &ld->ld_ret_ctrls, 0);
478*0Sstevel@tonic-gate if (retcode == LDAP_SUCCESS)
479*0Sstevel@tonic-gate retcode = ld->ld_errno;
480*0Sstevel@tonic-gate #ifdef _REENTRANT
481*0Sstevel@tonic-gate UNLOCK_LDAP(ld);
482*0Sstevel@tonic-gate #endif
483*0Sstevel@tonic-gate
484*0Sstevel@tonic-gate return (retcode);
485*0Sstevel@tonic-gate }
486*0Sstevel@tonic-gate
487*0Sstevel@tonic-gate
488*0Sstevel@tonic-gate static void
hex_unescape(char * s)489*0Sstevel@tonic-gate hex_unescape( char *s )
490*0Sstevel@tonic-gate {
491*0Sstevel@tonic-gate /*
492*0Sstevel@tonic-gate * Remove URL hex escapes from s... done in place. The basic concept for
493*0Sstevel@tonic-gate * this routine is borrowed from the WWW library HTUnEscape() routine.
494*0Sstevel@tonic-gate */
495*0Sstevel@tonic-gate char *p;
496*0Sstevel@tonic-gate
497*0Sstevel@tonic-gate for ( p = s; *s != '\0'; ++s ) {
498*0Sstevel@tonic-gate if ( *s == '%' ) {
499*0Sstevel@tonic-gate if ( *++s != '\0' ) {
500*0Sstevel@tonic-gate *p = unhex( *s ) << 4;
501*0Sstevel@tonic-gate }
502*0Sstevel@tonic-gate if ( *++s != '\0' ) {
503*0Sstevel@tonic-gate *p++ += unhex( *s );
504*0Sstevel@tonic-gate }
505*0Sstevel@tonic-gate } else {
506*0Sstevel@tonic-gate *p++ = *s;
507*0Sstevel@tonic-gate }
508*0Sstevel@tonic-gate }
509*0Sstevel@tonic-gate
510*0Sstevel@tonic-gate *p = '\0';
511*0Sstevel@tonic-gate }
512*0Sstevel@tonic-gate
513*0Sstevel@tonic-gate
514*0Sstevel@tonic-gate static int
unhex(char c)515*0Sstevel@tonic-gate unhex( char c )
516*0Sstevel@tonic-gate {
517*0Sstevel@tonic-gate return( c >= '0' && c <= '9' ? c - '0'
518*0Sstevel@tonic-gate : c >= 'A' && c <= 'F' ? c - 'A' + 10
519*0Sstevel@tonic-gate : c - 'a' + 10 );
520*0Sstevel@tonic-gate }
521*0Sstevel@tonic-gate
522*0Sstevel@tonic-gate
523*0Sstevel@tonic-gate /*
524*0Sstevel@tonic-gate * Locate the LDAP URL associated with a DNS domain name.
525*0Sstevel@tonic-gate *
526*0Sstevel@tonic-gate * The supplied DNS domain name is converted into a distinguished
527*0Sstevel@tonic-gate * name. The directory entry specified by that distinguished name
528*0Sstevel@tonic-gate * is searched for a labeledURI attribute. If successful then the
529*0Sstevel@tonic-gate * LDAP URL is returned. If unsuccessful then that entry's parent
530*0Sstevel@tonic-gate * is searched and so on until the target distinguished name is
531*0Sstevel@tonic-gate * reduced to only two nameparts.
532*0Sstevel@tonic-gate *
533*0Sstevel@tonic-gate * For example, if 'ny.eng.wiz.com' is the DNS domain then the
534*0Sstevel@tonic-gate * following entries are searched until one succeeds:
535*0Sstevel@tonic-gate * dc=ny,dc=eng,dc=wiz,dc=com
536*0Sstevel@tonic-gate * dc=eng,dc=wiz,dc=com
537*0Sstevel@tonic-gate * dc=wiz,dc=com
538*0Sstevel@tonic-gate *
539*0Sstevel@tonic-gate * If dns_name is NULL then the environment variable LOCALDOMAIN is used.
540*0Sstevel@tonic-gate * If attrs is not NULL then it is appended to the URL's attribute list.
541*0Sstevel@tonic-gate * If scope is not NULL then it overrides the URL's scope.
542*0Sstevel@tonic-gate * If filter is not NULL then it is merged with the URL's filter.
543*0Sstevel@tonic-gate *
544*0Sstevel@tonic-gate * If an error is encountered then zero is returned, otherwise a string
545*0Sstevel@tonic-gate * URL is returned. The caller should free the returned string if it is
546*0Sstevel@tonic-gate * non-zero.
547*0Sstevel@tonic-gate */
548*0Sstevel@tonic-gate
549*0Sstevel@tonic-gate char *
ldap_dns_to_url(LDAP * ld,char * dns_name,char * attrs,char * scope,char * filter)550*0Sstevel@tonic-gate ldap_dns_to_url(
551*0Sstevel@tonic-gate LDAP *ld,
552*0Sstevel@tonic-gate char *dns_name,
553*0Sstevel@tonic-gate char *attrs,
554*0Sstevel@tonic-gate char *scope,
555*0Sstevel@tonic-gate char *filter
556*0Sstevel@tonic-gate )
557*0Sstevel@tonic-gate {
558*0Sstevel@tonic-gate char *dn;
559*0Sstevel@tonic-gate char *url = 0;
560*0Sstevel@tonic-gate char *url2 = 0;
561*0Sstevel@tonic-gate LDAPURLDesc *urldesc;
562*0Sstevel@tonic-gate char *cp;
563*0Sstevel@tonic-gate char *cp2;
564*0Sstevel@tonic-gate size_t attrs_len = 0;
565*0Sstevel@tonic-gate size_t scope_len = 0;
566*0Sstevel@tonic-gate size_t filter_len = 0;
567*0Sstevel@tonic-gate int nameparts;
568*0Sstevel@tonic-gate int no_attrs = 0;
569*0Sstevel@tonic-gate int no_scope = 0;
570*0Sstevel@tonic-gate
571*0Sstevel@tonic-gate if (dns_name == 0) {
572*0Sstevel@tonic-gate dns_name = (char *)getenv("LOCALDOMAIN");
573*0Sstevel@tonic-gate }
574*0Sstevel@tonic-gate
575*0Sstevel@tonic-gate if ((ld == NULL) || ((dn = ldap_dns_to_dn(dns_name, &nameparts)) ==
576*0Sstevel@tonic-gate NULL))
577*0Sstevel@tonic-gate return (0);
578*0Sstevel@tonic-gate
579*0Sstevel@tonic-gate if ((url = ldap_dn_to_url(ld, dn, nameparts)) == NULL) {
580*0Sstevel@tonic-gate free(dn);
581*0Sstevel@tonic-gate return (0);
582*0Sstevel@tonic-gate }
583*0Sstevel@tonic-gate free(dn);
584*0Sstevel@tonic-gate
585*0Sstevel@tonic-gate /* merge filter and/or scope and/or attributes with URL */
586*0Sstevel@tonic-gate if (attrs || scope || filter) {
587*0Sstevel@tonic-gate
588*0Sstevel@tonic-gate if (attrs)
589*0Sstevel@tonic-gate attrs_len = strlen(attrs) + 2; /* for comma and NULL */
590*0Sstevel@tonic-gate
591*0Sstevel@tonic-gate if (scope)
592*0Sstevel@tonic-gate scope_len = strlen(scope) + 1; /* for NULL */
593*0Sstevel@tonic-gate
594*0Sstevel@tonic-gate if (filter)
595*0Sstevel@tonic-gate filter_len = strlen(filter) + 4;
596*0Sstevel@tonic-gate /* for ampersand, parentheses and NULL */
597*0Sstevel@tonic-gate
598*0Sstevel@tonic-gate if (ldap_is_ldap_url(url)) {
599*0Sstevel@tonic-gate
600*0Sstevel@tonic-gate if ((url2 = (char *)malloc(attrs_len + scope_len +
601*0Sstevel@tonic-gate filter_len + strlen(url) + 1)) == NULL) {
602*0Sstevel@tonic-gate return (0);
603*0Sstevel@tonic-gate }
604*0Sstevel@tonic-gate cp = url;
605*0Sstevel@tonic-gate cp2 = url2;
606*0Sstevel@tonic-gate
607*0Sstevel@tonic-gate /* copy URL scheme, hostname, port number and DN */
608*0Sstevel@tonic-gate while (*cp && (*cp != '?')) {
609*0Sstevel@tonic-gate *cp2++ = *cp++;
610*0Sstevel@tonic-gate }
611*0Sstevel@tonic-gate
612*0Sstevel@tonic-gate /* handle URL attributes */
613*0Sstevel@tonic-gate
614*0Sstevel@tonic-gate if (*cp == '?') { /* test first '?' */
615*0Sstevel@tonic-gate *cp2++ = *cp++; /* copy first '?' */
616*0Sstevel@tonic-gate
617*0Sstevel@tonic-gate if (*cp == '?') { /* test second '?' */
618*0Sstevel@tonic-gate
619*0Sstevel@tonic-gate /* insert supplied attributes */
620*0Sstevel@tonic-gate if (attrs) {
621*0Sstevel@tonic-gate while (*attrs) {
622*0Sstevel@tonic-gate *cp2++ = *attrs++;
623*0Sstevel@tonic-gate }
624*0Sstevel@tonic-gate } else {
625*0Sstevel@tonic-gate no_attrs = 1;
626*0Sstevel@tonic-gate }
627*0Sstevel@tonic-gate
628*0Sstevel@tonic-gate } else {
629*0Sstevel@tonic-gate
630*0Sstevel@tonic-gate /* copy URL attributes */
631*0Sstevel@tonic-gate while (*cp && (*cp != '?')) {
632*0Sstevel@tonic-gate *cp2++ = *cp++;
633*0Sstevel@tonic-gate }
634*0Sstevel@tonic-gate
635*0Sstevel@tonic-gate /* append supplied attributes */
636*0Sstevel@tonic-gate if (attrs) {
637*0Sstevel@tonic-gate *cp2++ = ',';
638*0Sstevel@tonic-gate while (*attrs) {
639*0Sstevel@tonic-gate *cp2++ = *attrs++;
640*0Sstevel@tonic-gate }
641*0Sstevel@tonic-gate }
642*0Sstevel@tonic-gate }
643*0Sstevel@tonic-gate
644*0Sstevel@tonic-gate } else {
645*0Sstevel@tonic-gate /* append supplied attributes */
646*0Sstevel@tonic-gate if (attrs) {
647*0Sstevel@tonic-gate *cp2++ = '?';
648*0Sstevel@tonic-gate while (*attrs) {
649*0Sstevel@tonic-gate *cp2++ = *attrs++;
650*0Sstevel@tonic-gate }
651*0Sstevel@tonic-gate } else {
652*0Sstevel@tonic-gate no_attrs = 1;
653*0Sstevel@tonic-gate }
654*0Sstevel@tonic-gate }
655*0Sstevel@tonic-gate
656*0Sstevel@tonic-gate /* handle URL scope */
657*0Sstevel@tonic-gate
658*0Sstevel@tonic-gate if (*cp == '?') { /* test second '?' */
659*0Sstevel@tonic-gate *cp2++ = *cp++; /* copy second '?' */
660*0Sstevel@tonic-gate
661*0Sstevel@tonic-gate if (*cp == '?') { /* test third '?' */
662*0Sstevel@tonic-gate
663*0Sstevel@tonic-gate /* insert supplied scope */
664*0Sstevel@tonic-gate if (scope) {
665*0Sstevel@tonic-gate while (*scope) {
666*0Sstevel@tonic-gate *cp2++ = *scope++;
667*0Sstevel@tonic-gate }
668*0Sstevel@tonic-gate } else {
669*0Sstevel@tonic-gate no_scope = 1;
670*0Sstevel@tonic-gate }
671*0Sstevel@tonic-gate
672*0Sstevel@tonic-gate } else {
673*0Sstevel@tonic-gate
674*0Sstevel@tonic-gate if (scope) {
675*0Sstevel@tonic-gate /* skip over URL scope */
676*0Sstevel@tonic-gate while (*cp && (*cp != '?')) {
677*0Sstevel@tonic-gate *cp++;
678*0Sstevel@tonic-gate }
679*0Sstevel@tonic-gate /* insert supplied scope */
680*0Sstevel@tonic-gate while (*scope) {
681*0Sstevel@tonic-gate *cp2++ = *scope++;
682*0Sstevel@tonic-gate }
683*0Sstevel@tonic-gate } else {
684*0Sstevel@tonic-gate
685*0Sstevel@tonic-gate /* copy URL scope */
686*0Sstevel@tonic-gate while (*cp && (*cp != '?')) {
687*0Sstevel@tonic-gate *cp2++ = *cp++;
688*0Sstevel@tonic-gate }
689*0Sstevel@tonic-gate }
690*0Sstevel@tonic-gate }
691*0Sstevel@tonic-gate
692*0Sstevel@tonic-gate } else {
693*0Sstevel@tonic-gate /* append supplied scope */
694*0Sstevel@tonic-gate if (scope) {
695*0Sstevel@tonic-gate if (no_attrs) {
696*0Sstevel@tonic-gate *cp2++ = '?';
697*0Sstevel@tonic-gate }
698*0Sstevel@tonic-gate *cp2++ = '?';
699*0Sstevel@tonic-gate while (*scope) {
700*0Sstevel@tonic-gate *cp2++ = *scope++;
701*0Sstevel@tonic-gate }
702*0Sstevel@tonic-gate } else {
703*0Sstevel@tonic-gate no_scope = 1;
704*0Sstevel@tonic-gate }
705*0Sstevel@tonic-gate }
706*0Sstevel@tonic-gate
707*0Sstevel@tonic-gate /* handle URL filter */
708*0Sstevel@tonic-gate
709*0Sstevel@tonic-gate if (*cp == '?') { /* test third '?' */
710*0Sstevel@tonic-gate *cp2++ = *cp++; /* copy third '?' */
711*0Sstevel@tonic-gate
712*0Sstevel@tonic-gate if (filter) {
713*0Sstevel@tonic-gate
714*0Sstevel@tonic-gate /* merge URL and supplied filters */
715*0Sstevel@tonic-gate
716*0Sstevel@tonic-gate *cp2++ = '(';
717*0Sstevel@tonic-gate *cp2++ = '&';
718*0Sstevel@tonic-gate /* copy URL filter */
719*0Sstevel@tonic-gate while (*cp) {
720*0Sstevel@tonic-gate *cp2++ = *cp++;
721*0Sstevel@tonic-gate }
722*0Sstevel@tonic-gate /* append supplied filter */
723*0Sstevel@tonic-gate while (*filter) {
724*0Sstevel@tonic-gate *cp2++ = *filter++;
725*0Sstevel@tonic-gate }
726*0Sstevel@tonic-gate *cp2++ = ')';
727*0Sstevel@tonic-gate } else {
728*0Sstevel@tonic-gate
729*0Sstevel@tonic-gate /* copy URL filter */
730*0Sstevel@tonic-gate while (*cp) {
731*0Sstevel@tonic-gate *cp2++ = *cp++;
732*0Sstevel@tonic-gate }
733*0Sstevel@tonic-gate }
734*0Sstevel@tonic-gate
735*0Sstevel@tonic-gate } else {
736*0Sstevel@tonic-gate /* append supplied filter */
737*0Sstevel@tonic-gate if (filter) {
738*0Sstevel@tonic-gate if (no_scope) {
739*0Sstevel@tonic-gate if (no_attrs) {
740*0Sstevel@tonic-gate *cp2++ = '?';
741*0Sstevel@tonic-gate }
742*0Sstevel@tonic-gate *cp2++ = '?';
743*0Sstevel@tonic-gate }
744*0Sstevel@tonic-gate *cp2++ = '?';
745*0Sstevel@tonic-gate while (*filter) {
746*0Sstevel@tonic-gate *cp2++ = *filter++;
747*0Sstevel@tonic-gate }
748*0Sstevel@tonic-gate }
749*0Sstevel@tonic-gate }
750*0Sstevel@tonic-gate
751*0Sstevel@tonic-gate *cp2++ = '\0';
752*0Sstevel@tonic-gate free (url);
753*0Sstevel@tonic-gate url = url2;
754*0Sstevel@tonic-gate
755*0Sstevel@tonic-gate } else {
756*0Sstevel@tonic-gate return (0); /* not an LDAP URL */
757*0Sstevel@tonic-gate }
758*0Sstevel@tonic-gate }
759*0Sstevel@tonic-gate return (url);
760*0Sstevel@tonic-gate }
761*0Sstevel@tonic-gate
762*0Sstevel@tonic-gate
763*0Sstevel@tonic-gate /*
764*0Sstevel@tonic-gate * Locate the LDAP URL associated with a distinguished name.
765*0Sstevel@tonic-gate *
766*0Sstevel@tonic-gate * The number of nameparts in the supplied distinguished name must be
767*0Sstevel@tonic-gate * provided. The specified directory entry is searched for a labeledURI
768*0Sstevel@tonic-gate * attribute. If successful then the LDAP URL is returned. If unsuccessful
769*0Sstevel@tonic-gate * then that entry's parent is searched and so on until the target
770*0Sstevel@tonic-gate * distinguished name is reduced to only two nameparts.
771*0Sstevel@tonic-gate *
772*0Sstevel@tonic-gate * For example, if 'l=ny,ou=eng,o=wiz,c=us' is the distinguished name
773*0Sstevel@tonic-gate * then the following entries are searched until one succeeds:
774*0Sstevel@tonic-gate * l=ny,ou=eng,o=wiz,c=us
775*0Sstevel@tonic-gate * ou=eng,o=wiz,c=us
776*0Sstevel@tonic-gate * o=wiz,c=us
777*0Sstevel@tonic-gate *
778*0Sstevel@tonic-gate * If an error is encountered then zero is returned, otherwise a string
779*0Sstevel@tonic-gate * URL is returned. The caller should free the returned string if it is
780*0Sstevel@tonic-gate * non-zero.
781*0Sstevel@tonic-gate */
782*0Sstevel@tonic-gate
783*0Sstevel@tonic-gate char *
ldap_dn_to_url(LDAP * ld,char * dn,int nameparts)784*0Sstevel@tonic-gate ldap_dn_to_url(
785*0Sstevel@tonic-gate LDAP *ld,
786*0Sstevel@tonic-gate char *dn,
787*0Sstevel@tonic-gate int nameparts
788*0Sstevel@tonic-gate )
789*0Sstevel@tonic-gate {
790*0Sstevel@tonic-gate char *next_dn = dn;
791*0Sstevel@tonic-gate char *url = 0;
792*0Sstevel@tonic-gate char *attrs[2] = {"labeledURI", 0};
793*0Sstevel@tonic-gate LDAPMessage *res, *e;
794*0Sstevel@tonic-gate char **vals;
795*0Sstevel@tonic-gate
796*0Sstevel@tonic-gate /*
797*0Sstevel@tonic-gate * Search for a URL in the named entry or its parent entry.
798*0Sstevel@tonic-gate * Continue until only 2 nameparts remain.
799*0Sstevel@tonic-gate */
800*0Sstevel@tonic-gate while (dn && (nameparts > 1) && (! url)) {
801*0Sstevel@tonic-gate
802*0Sstevel@tonic-gate /* search for the labeledURI attribute */
803*0Sstevel@tonic-gate if (ldap_search_s(ld, dn, LDAP_SCOPE_BASE,
804*0Sstevel@tonic-gate "(objectClass=*)", attrs, 0, &res) == LDAP_SUCCESS) {
805*0Sstevel@tonic-gate
806*0Sstevel@tonic-gate /* locate the first entry returned */
807*0Sstevel@tonic-gate if ((e = ldap_first_entry(ld, res)) != NULL) {
808*0Sstevel@tonic-gate
809*0Sstevel@tonic-gate /* locate the labeledURI attribute */
810*0Sstevel@tonic-gate if ((vals =
811*0Sstevel@tonic-gate ldap_get_values(ld, e, "labeledURI")) !=
812*0Sstevel@tonic-gate NULL) {
813*0Sstevel@tonic-gate
814*0Sstevel@tonic-gate /* copy the attribute value */
815*0Sstevel@tonic-gate if ((url = strdup((char *)vals[0])) !=
816*0Sstevel@tonic-gate NULL) {
817*0Sstevel@tonic-gate ldap_value_free(vals);
818*0Sstevel@tonic-gate }
819*0Sstevel@tonic-gate }
820*0Sstevel@tonic-gate }
821*0Sstevel@tonic-gate /* free the search results */
822*0Sstevel@tonic-gate ldap_msgfree(res);
823*0Sstevel@tonic-gate }
824*0Sstevel@tonic-gate
825*0Sstevel@tonic-gate if (! url) {
826*0Sstevel@tonic-gate /* advance along the DN by one namepart */
827*0Sstevel@tonic-gate if (next_dn = strchr(dn, ',')) {
828*0Sstevel@tonic-gate next_dn++;
829*0Sstevel@tonic-gate dn = next_dn;
830*0Sstevel@tonic-gate nameparts--;
831*0Sstevel@tonic-gate }
832*0Sstevel@tonic-gate }
833*0Sstevel@tonic-gate }
834*0Sstevel@tonic-gate
835*0Sstevel@tonic-gate return (url);
836*0Sstevel@tonic-gate }
837