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