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