1 /* $NetBSD: deref.c,v 1.1.1.1 2010/03/08 02:14:20 lukem Exp $ */ 2 3 /* OpenLDAP: pkg/ldap/libraries/libldap/deref.c,v 1.2.2.2 2009/01/22 00:00:54 kurt Exp */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2009 The OpenLDAP Foundation. 7 * Portions Copyright 2008 Pierangelo Masarati. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 /* ACKNOWLEDGEMENTS: 19 * This work was initially developed by Pierangelo Masarati 20 * for inclusion in OpenLDAP Software. 21 */ 22 23 #include "portable.h" 24 25 #include <stdio.h> 26 #include <ac/stdlib.h> 27 #include <ac/string.h> 28 #include <ac/time.h> 29 30 #include "ldap-int.h" 31 32 int 33 ldap_create_deref_control_value( 34 LDAP *ld, 35 LDAPDerefSpec *ds, 36 struct berval *value ) 37 { 38 BerElement *ber = NULL; 39 ber_tag_t tag; 40 int i; 41 42 if ( ld == NULL || value == NULL || ds == NULL ) 43 { 44 if ( ld ) 45 ld->ld_errno = LDAP_PARAM_ERROR; 46 return LDAP_PARAM_ERROR; 47 } 48 49 assert( LDAP_VALID( ld ) ); 50 51 value->bv_val = NULL; 52 value->bv_len = 0; 53 ld->ld_errno = LDAP_SUCCESS; 54 55 ber = ldap_alloc_ber_with_options( ld ); 56 if ( ber == NULL ) { 57 ld->ld_errno = LDAP_NO_MEMORY; 58 return ld->ld_errno; 59 } 60 61 tag = ber_printf( ber, "{" /*}*/ ); 62 if ( tag == LBER_ERROR ) { 63 ld->ld_errno = LDAP_ENCODING_ERROR; 64 goto done; 65 } 66 67 for ( i = 0; ds[i].derefAttr != NULL; i++ ) { 68 int j; 69 70 tag = ber_printf( ber, "{s{" /*}}*/ , ds[i].derefAttr ); 71 if ( tag == LBER_ERROR ) { 72 ld->ld_errno = LDAP_ENCODING_ERROR; 73 goto done; 74 } 75 76 for ( j = 0; ds[i].attributes[j] != NULL; j++ ) { 77 tag = ber_printf( ber, "s", ds[i].attributes[ j ] ); 78 if ( tag == LBER_ERROR ) { 79 ld->ld_errno = LDAP_ENCODING_ERROR; 80 goto done; 81 } 82 } 83 84 tag = ber_printf( ber, /*{{*/ "}N}" ); 85 if ( tag == LBER_ERROR ) { 86 ld->ld_errno = LDAP_ENCODING_ERROR; 87 goto done; 88 } 89 } 90 91 tag = ber_printf( ber, /*{*/ "}" ); 92 if ( tag == LBER_ERROR ) { 93 ld->ld_errno = LDAP_ENCODING_ERROR; 94 goto done; 95 } 96 97 if ( ber_flatten2( ber, value, 1 ) == -1 ) { 98 ld->ld_errno = LDAP_NO_MEMORY; 99 } 100 101 done:; 102 if ( ber != NULL ) { 103 ber_free( ber, 1 ); 104 } 105 106 return ld->ld_errno; 107 } 108 109 int 110 ldap_create_deref_control( 111 LDAP *ld, 112 LDAPDerefSpec *ds, 113 int iscritical, 114 LDAPControl **ctrlp ) 115 { 116 struct berval value; 117 118 if ( ctrlp == NULL ) { 119 ld->ld_errno = LDAP_PARAM_ERROR; 120 return ld->ld_errno; 121 } 122 123 ld->ld_errno = ldap_create_deref_control_value( ld, ds, &value ); 124 if ( ld->ld_errno == LDAP_SUCCESS ) { 125 ld->ld_errno = ldap_control_create( LDAP_CONTROL_PAGEDRESULTS, 126 iscritical, &value, 0, ctrlp ); 127 if ( ld->ld_errno != LDAP_SUCCESS ) { 128 LDAP_FREE( value.bv_val ); 129 } 130 } 131 132 return ld->ld_errno; 133 } 134 135 void 136 ldap_derefresponse_free( LDAPDerefRes *dr ) 137 { 138 for ( ; dr; ) { 139 LDAPDerefRes *drnext = dr->next; 140 LDAPDerefVal *dv; 141 142 LDAP_FREE( dr->derefAttr ); 143 LDAP_FREE( dr->derefVal.bv_val ); 144 145 for ( dv = dr->attrVals; dv; ) { 146 LDAPDerefVal *dvnext = dv->next; 147 LDAP_FREE( dv->type ); 148 ber_bvarray_free( dv->vals ); 149 LDAP_FREE( dv ); 150 dv = dvnext; 151 } 152 153 LDAP_FREE( dr ); 154 155 dr = drnext; 156 } 157 } 158 159 int 160 ldap_parse_derefresponse_control( 161 LDAP *ld, 162 LDAPControl *ctrl, 163 LDAPDerefRes **drp2 ) 164 { 165 BerElement *ber; 166 ber_tag_t tag; 167 ber_len_t len; 168 char *last; 169 LDAPDerefRes *drhead = NULL, **drp; 170 171 if ( ld == NULL || ctrl == NULL || drp2 == NULL ) { 172 if ( ld ) 173 ld->ld_errno = LDAP_PARAM_ERROR; 174 return LDAP_PARAM_ERROR; 175 } 176 177 /* Create a BerElement from the berval returned in the control. */ 178 ber = ber_init( &ctrl->ldctl_value ); 179 180 if ( ber == NULL ) { 181 ld->ld_errno = LDAP_NO_MEMORY; 182 return ld->ld_errno; 183 } 184 185 /* Extract the count and cookie from the control. */ 186 drp = &drhead; 187 for ( tag = ber_first_element( ber, &len, &last ); 188 tag != LBER_DEFAULT; 189 tag = ber_next_element( ber, &len, last ) ) 190 { 191 LDAPDerefRes *dr; 192 LDAPDerefVal **dvp; 193 char *last2; 194 195 dr = LDAP_CALLOC( 1, sizeof(LDAPDerefRes) ); 196 dvp = &dr->attrVals; 197 198 tag = ber_scanf( ber, "{ao", &dr->derefAttr, &dr->derefVal ); 199 if ( tag == LBER_ERROR ) { 200 goto done; 201 } 202 203 tag = ber_peek_tag( ber, &len ); 204 if ( tag == (LBER_CONSTRUCTED|LBER_CLASS_CONTEXT) ) { 205 for ( tag = ber_first_element( ber, &len, &last2 ); 206 tag != LBER_DEFAULT; 207 tag = ber_next_element( ber, &len, last2 ) ) 208 { 209 LDAPDerefVal *dv; 210 211 dv = LDAP_CALLOC( 1, sizeof(LDAPDerefVal) ); 212 213 tag = ber_scanf( ber, "{a[W]}", &dv->type, &dv->vals ); 214 if ( tag == LBER_ERROR ) { 215 goto done; 216 } 217 218 *dvp = dv; 219 dvp = &dv->next; 220 } 221 } 222 223 tag = ber_scanf( ber, "}" ); 224 if ( tag == LBER_ERROR ) { 225 goto done; 226 } 227 228 *drp = dr; 229 drp = &dr->next; 230 } 231 232 tag = 0; 233 234 done:; 235 ber_free( ber, 1 ); 236 237 if ( tag == LBER_ERROR ) { 238 if ( drhead != NULL ) { 239 ldap_derefresponse_free( drhead ); 240 } 241 242 *drp2 = NULL; 243 ld->ld_errno = LDAP_DECODING_ERROR; 244 245 } else { 246 *drp2 = drhead; 247 ld->ld_errno = LDAP_SUCCESS; 248 } 249 250 return ld->ld_errno; 251 } 252 253 int 254 ldap_parse_deref_control( 255 LDAP *ld, 256 LDAPControl **ctrls, 257 LDAPDerefRes **drp ) 258 { 259 LDAPControl *c; 260 261 if ( drp == NULL ) { 262 ld->ld_errno = LDAP_PARAM_ERROR; 263 return ld->ld_errno; 264 } 265 266 *drp = NULL; 267 268 if ( ctrls == NULL ) { 269 ld->ld_errno = LDAP_CONTROL_NOT_FOUND; 270 return ld->ld_errno; 271 } 272 273 c = ldap_control_find( LDAP_CONTROL_X_DEREF, ctrls, NULL ); 274 if ( c == NULL ) { 275 /* No deref control was found. */ 276 ld->ld_errno = LDAP_CONTROL_NOT_FOUND; 277 return ld->ld_errno; 278 } 279 280 ld->ld_errno = ldap_parse_derefresponse_control( ld, c, drp ); 281 282 return ld->ld_errno; 283 } 284 285