1 /* 2 * Copyright (c) 2001 by Sun Microsystems, Inc. 3 * All rights reserved. 4 */ 5 6 /* 7 * The contents of this file are subject to the Netscape Public 8 * License Version 1.1 (the "License"); you may not use this file 9 * except in compliance with the License. You may obtain a copy of 10 * the License at http://www.mozilla.org/NPL/ 11 * 12 * Software distributed under the License is distributed on an "AS 13 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 14 * implied. See the License for the specific language governing 15 * rights and limitations under the License. 16 * 17 * The Original Code is Mozilla Communicator client code, released 18 * March 31, 1998. 19 * 20 * The Initial Developer of the Original Code is Netscape 21 * Communications Corporation. Portions created by Netscape are 22 * Copyright (C) 1998-1999 Netscape Communications Corporation. All 23 * Rights Reserved. 24 * 25 * Contributor(s): 26 */ 27 /* 28 * referral.c - routines for handling LDAPv3 referrals and references. 29 */ 30 31 #include "ldap-int.h" 32 33 34 LDAPMessage * 35 LDAP_CALL 36 ldap_first_reference( LDAP *ld, LDAPMessage *res ) 37 { 38 if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || res == NULLMSG ) { 39 return( NULLMSG ); 40 } 41 42 if ( res->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { 43 return( res ); 44 } 45 46 return( ldap_next_reference( ld, res )); 47 } 48 49 50 LDAPMessage * 51 LDAP_CALL 52 ldap_next_reference( LDAP *ld, LDAPMessage *ref ) 53 { 54 if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || ref == NULLMSG ) { 55 return( NULLMSG ); /* punt */ 56 } 57 58 for ( ref = ref->lm_chain; ref != NULLMSG; ref = ref->lm_chain ) { 59 if ( ref->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { 60 return( ref ); 61 } 62 } 63 64 return( NULLMSG ); 65 } 66 67 68 int 69 LDAP_CALL 70 ldap_count_references( LDAP *ld, LDAPMessage *res ) 71 { 72 int i; 73 74 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { 75 return( -1 ); 76 } 77 78 for ( i = 0; res != NULL; res = res->lm_chain ) { 79 if ( res->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { 80 ++i; 81 } 82 } 83 84 return( i ); 85 } 86 87 88 /* 89 * returns an LDAP error code. 90 */ 91 int 92 LDAP_CALL 93 ldap_parse_reference( LDAP *ld, LDAPMessage *ref, char ***referralsp, 94 LDAPControl ***serverctrlsp, int freeit ) 95 { 96 int err; 97 98 if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || 99 !NSLDAPI_VALID_LDAPMESSAGE_REFERENCE_POINTER( ref )) { 100 return( LDAP_PARAM_ERROR ); 101 } 102 103 err = nsldapi_parse_reference( ld, ref->lm_ber, referralsp, 104 serverctrlsp ); 105 106 LDAP_SET_LDERRNO( ld, err, NULL, NULL ); 107 108 if ( freeit ) { 109 ldap_msgfree( ref ); 110 } 111 112 return( err ); 113 } 114 115 116 /* 117 * returns an LDAP error code indicating success or failure of parsing 118 * does NOT set any error information inside "ld" 119 */ 120 int 121 nsldapi_parse_reference( LDAP *ld, BerElement *rber, char ***referralsp, 122 LDAPControl ***serverctrlsp ) 123 { 124 int err; 125 BerElement ber; 126 char **refs; 127 128 /* 129 * Parse a searchResultReference message. These are used in LDAPv3 130 * and beyond and look like this: 131 * 132 * SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL 133 * 134 * all wrapped up in an LDAPMessage sequence which looks like this: 135 * 136 * LDAPMessage ::= SEQUENCE { 137 * messageID MessageID, 138 * SearchResultReference 139 * controls [0] Controls OPTIONAL 140 * } 141 * 142 * ldap_result() pulls out the message id, so by the time a result 143 * message gets here we are conveniently sitting at the start of the 144 * SearchResultReference itself. 145 */ 146 err = LDAP_SUCCESS; /* optimistic */ 147 ber = *rber; /* struct copy */ 148 149 if ( ber_scanf( &ber, "{v", &refs ) == LBER_ERROR ) { 150 err = LDAP_DECODING_ERROR; 151 } else if ( serverctrlsp != NULL ) { 152 /* pull out controls (if requested and any are present) */ 153 if ( ber_scanf( &ber, "}" ) == LBER_ERROR ) { 154 err = LDAP_DECODING_ERROR; 155 } else { 156 err = nsldapi_get_controls( &ber, serverctrlsp ); 157 } 158 } 159 160 if ( referralsp == NULL ) { 161 ldap_value_free( refs ); 162 } else { 163 *referralsp = refs; 164 } 165 166 return( err ); 167 } 168 169 #ifdef _SOLARIS_SDK 170 171 char ** ldap_get_reference_urls(LDAP *ld, LDAPMessage *res) 172 { 173 BerElement tmp; 174 char **urls = NULL; 175 176 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_reference_urls\n", 0, 0, 0 ); 177 178 if (res == NULL){ 179 ld->ld_errno = LDAP_PARAM_ERROR; 180 return (NULL); 181 } 182 tmp = *res->lm_ber; /* struct copy */ 183 if ( ber_scanf( &tmp, "{v}", &urls) == LBER_ERROR){ 184 ld->ld_errno = LDAP_DECODING_ERROR; 185 return (NULL); 186 } 187 return (urls); 188 } 189 190 #endif /* _SOLARIS_SDK */ 191 192