1/* $OpenLDAP$ */ 2/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 1998-2011 The OpenLDAP Foundation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted only as authorized by the OpenLDAP 9 * Public License. 10 * 11 * A copy of this license is available in the file LICENSE in the 12 * top-level directory of the distribution or, alternatively, at 13 * <http://www.OpenLDAP.org/license.html>. 14 */ 15/* This notice applies to changes, created by or for Novell, Inc., 16 * to preexisting works for which notices appear elsewhere in this file. 17 * 18 * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. 19 * 20 * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. 21 * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION 22 * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT 23 * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE 24 * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS 25 * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC 26 * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE 27 * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. 28 *--- 29 * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License 30 * can be found in the file "build/LICENSE-2.0.1" in this distribution 31 * of OpenLDAP Software. 32 */ 33 34#include "portable.h" 35 36#include <ac/stdlib.h> 37 38#include <ac/time.h> 39#include <ac/string.h> 40 41#include "ldap-int.h" 42 43/* LDAPv3 Controls (RFC 4511) 44 * 45 * Controls ::= SEQUENCE OF control Control 46 * 47 * Control ::= SEQUENCE { 48 * controlType LDAPOID, 49 * criticality BOOLEAN DEFAULT FALSE, 50 * controlValue OCTET STRING OPTIONAL 51 * } 52 */ 53 54int 55ldap_pvt_put_control( 56 const LDAPControl *c, 57 BerElement *ber ) 58{ 59 if ( ber_printf( ber, "{s" /*}*/, c->ldctl_oid ) == -1 ) { 60 return LDAP_ENCODING_ERROR; 61 } 62 63 if ( c->ldctl_iscritical /* only if true */ 64 && ( ber_printf( ber, "b", 65 (ber_int_t) c->ldctl_iscritical ) == -1 ) ) 66 { 67 return LDAP_ENCODING_ERROR; 68 } 69 70 if ( !BER_BVISNULL( &c->ldctl_value ) /* only if we have a value */ 71 && ( ber_printf( ber, "O", &c->ldctl_value ) == -1 ) ) 72 { 73 return LDAP_ENCODING_ERROR; 74 } 75 76 if ( ber_printf( ber, /*{*/"N}" ) == -1 ) { 77 return LDAP_ENCODING_ERROR; 78 } 79 80 return LDAP_SUCCESS; 81} 82 83 84/* 85 * ldap_int_put_controls 86 */ 87 88int 89ldap_int_put_controls( 90 LDAP *ld, 91 LDAPControl *const *ctrls, 92 BerElement *ber ) 93{ 94 LDAPControl *const *c; 95 96 assert( ld != NULL ); 97 assert( LDAP_VALID( ld ) ); 98 assert( ber != NULL ); 99 100 if( ctrls == NULL ) { 101 /* use default server controls */ 102 ctrls = ld->ld_sctrls; 103 } 104 105 if( ctrls == NULL || *ctrls == NULL ) { 106 return LDAP_SUCCESS; 107 } 108 109 if ( ld->ld_version < LDAP_VERSION3 ) { 110 /* LDAPv2 doesn't support controls, 111 * error if any control is critical 112 */ 113 for( c = ctrls ; *c != NULL; c++ ) { 114 if( (*c)->ldctl_iscritical ) { 115 ld->ld_errno = LDAP_NOT_SUPPORTED; 116 return ld->ld_errno; 117 } 118 } 119 120 return LDAP_SUCCESS; 121 } 122 123 /* Controls are encoded as a sequence of sequences */ 124 if( ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ) == -1 ) { 125 ld->ld_errno = LDAP_ENCODING_ERROR; 126 return ld->ld_errno; 127 } 128 129 for( c = ctrls ; *c != NULL; c++ ) { 130 ld->ld_errno = ldap_pvt_put_control( *c, ber ); 131 if ( ld->ld_errno != LDAP_SUCCESS ) { 132 return ld->ld_errno; 133 } 134 } 135 136 137 if( ber_printf( ber, /*{*/ "}" ) == -1 ) { 138 ld->ld_errno = LDAP_ENCODING_ERROR; 139 return ld->ld_errno; 140 } 141 142 return LDAP_SUCCESS; 143} 144 145int ldap_pvt_get_controls( 146 BerElement *ber, 147 LDAPControl ***ctrls ) 148{ 149 int nctrls; 150 ber_tag_t tag; 151 ber_len_t len; 152 char *opaque; 153 154 assert( ber != NULL ); 155 156 if( ctrls == NULL ) { 157 return LDAP_SUCCESS; 158 } 159 *ctrls = NULL; 160 161 len = ber_pvt_ber_remaining( ber ); 162 163 if( len == 0) { 164 /* no controls */ 165 return LDAP_SUCCESS; 166 } 167 168 if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) { 169 if( tag == LBER_ERROR ) { 170 /* decoding error */ 171 return LDAP_DECODING_ERROR; 172 } 173 174 /* ignore unexpected input */ 175 return LDAP_SUCCESS; 176 } 177 178 /* set through each element */ 179 nctrls = 0; 180 *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) ); 181 182 if( *ctrls == NULL ) { 183 return LDAP_NO_MEMORY; 184 } 185 186 *ctrls[nctrls] = NULL; 187 188 for( tag = ber_first_element( ber, &len, &opaque ); 189 tag != LBER_ERROR; 190 tag = ber_next_element( ber, &len, opaque ) ) 191 { 192 LDAPControl *tctrl; 193 LDAPControl **tctrls; 194 195 tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) ); 196 197 /* allocate pointer space for current controls (nctrls) 198 * + this control + extra NULL 199 */ 200 tctrls = (tctrl == NULL) ? NULL : 201 LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *)); 202 203 if( tctrls == NULL ) { 204 /* one of the above allocation failed */ 205 206 if( tctrl != NULL ) { 207 LDAP_FREE( tctrl ); 208 } 209 210 ldap_controls_free(*ctrls); 211 *ctrls = NULL; 212 213 return LDAP_NO_MEMORY; 214 } 215 216 217 tctrls[nctrls++] = tctrl; 218 tctrls[nctrls] = NULL; 219 220 tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid ); 221 222 if( tag == LBER_ERROR ) { 223 *ctrls = NULL; 224 ldap_controls_free( tctrls ); 225 return LDAP_DECODING_ERROR; 226 } 227 228 tag = ber_peek_tag( ber, &len ); 229 230 if( tag == LBER_BOOLEAN ) { 231 ber_int_t crit; 232 tag = ber_scanf( ber, "b", &crit ); 233 tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0; 234 tag = ber_peek_tag( ber, &len ); 235 } 236 237 if( tag == LBER_OCTETSTRING ) { 238 tag = ber_scanf( ber, "o", &tctrl->ldctl_value ); 239 } else { 240 BER_BVZERO( &tctrl->ldctl_value ); 241 } 242 243 *ctrls = tctrls; 244 } 245 246 return LDAP_SUCCESS; 247} 248 249/* 250 * Free a LDAPControl 251 */ 252void 253ldap_control_free( LDAPControl *c ) 254{ 255 LDAP_MEMORY_DEBUG_ASSERT( c != NULL ); 256 257 if ( c != NULL ) { 258 if( c->ldctl_oid != NULL) { 259 LDAP_FREE( c->ldctl_oid ); 260 } 261 262 if( c->ldctl_value.bv_val != NULL ) { 263 LDAP_FREE( c->ldctl_value.bv_val ); 264 } 265 266 LDAP_FREE( c ); 267 } 268} 269 270/* 271 * Free an array of LDAPControl's 272 */ 273void 274ldap_controls_free( LDAPControl **controls ) 275{ 276 LDAP_MEMORY_DEBUG_ASSERT( controls != NULL ); 277 278 if ( controls != NULL ) { 279 int i; 280 281 for( i=0; controls[i] != NULL; i++) { 282 ldap_control_free( controls[i] ); 283 } 284 285 LDAP_FREE( controls ); 286 } 287} 288 289/* 290 * Duplicate an array of LDAPControl 291 */ 292LDAPControl ** 293ldap_controls_dup( LDAPControl *const *controls ) 294{ 295 LDAPControl **new; 296 int i; 297 298 if ( controls == NULL ) { 299 return NULL; 300 } 301 302 /* count the controls */ 303 for(i=0; controls[i] != NULL; i++) /* empty */ ; 304 305 if( i < 1 ) { 306 /* no controls to duplicate */ 307 return NULL; 308 } 309 310 new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) ); 311 312 if( new == NULL ) { 313 /* memory allocation failure */ 314 return NULL; 315 } 316 317 /* duplicate the controls */ 318 for(i=0; controls[i] != NULL; i++) { 319 new[i] = ldap_control_dup( controls[i] ); 320 321 if( new[i] == NULL ) { 322 ldap_controls_free( new ); 323 return NULL; 324 } 325 } 326 327 new[i] = NULL; 328 329 return new; 330} 331 332/* 333 * Duplicate a LDAPControl 334 */ 335LDAPControl * 336ldap_control_dup( const LDAPControl *c ) 337{ 338 LDAPControl *new; 339 340 if ( c == NULL || c->ldctl_oid == NULL ) { 341 return NULL; 342 } 343 344 new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) ); 345 346 if( new == NULL ) { 347 return NULL; 348 } 349 350 new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid ); 351 352 if(new->ldctl_oid == NULL) { 353 LDAP_FREE( new ); 354 return NULL; 355 } 356 357 if( c->ldctl_value.bv_val != NULL ) { 358 new->ldctl_value.bv_val = 359 (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 ); 360 361 if(new->ldctl_value.bv_val == NULL) { 362 if(new->ldctl_oid != NULL) { 363 LDAP_FREE( new->ldctl_oid ); 364 } 365 LDAP_FREE( new ); 366 return NULL; 367 } 368 369 new->ldctl_value.bv_len = c->ldctl_value.bv_len; 370 371 AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 372 c->ldctl_value.bv_len ); 373 374 new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0'; 375 376 } else { 377 new->ldctl_value.bv_len = 0; 378 new->ldctl_value.bv_val = NULL; 379 } 380 381 new->ldctl_iscritical = c->ldctl_iscritical; 382 return new; 383} 384 385/* 386 * Find a LDAPControl - deprecated 387 */ 388LDAPControl * 389ldap_find_control( 390 LDAP_CONST char *oid, 391 LDAPControl **ctrls ) 392{ 393 if( ctrls == NULL || *ctrls == NULL ) { 394 return NULL; 395 } 396 397 for( ; *ctrls != NULL; ctrls++ ) { 398 if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) { 399 return *ctrls; 400 } 401 } 402 403 return NULL; 404} 405 406/* 407 * Find a LDAPControl 408 */ 409LDAPControl * 410ldap_control_find( 411 LDAP_CONST char *oid, 412 LDAPControl **ctrls, 413 LDAPControl ***nextctrlp ) 414{ 415 if ( oid == NULL || ctrls == NULL || *ctrls == NULL ) { 416 return NULL; 417 } 418 419 for( ; *ctrls != NULL; ctrls++ ) { 420 if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) { 421 if ( nextctrlp != NULL ) { 422 *nextctrlp = ctrls + 1; 423 } 424 425 return *ctrls; 426 } 427 } 428 429 if ( nextctrlp != NULL ) { 430 *nextctrlp = NULL; 431 } 432 433 return NULL; 434} 435 436/* 437 * Create a LDAPControl, optionally from ber - deprecated 438 */ 439int 440ldap_create_control( 441 LDAP_CONST char *requestOID, 442 BerElement *ber, 443 int iscritical, 444 LDAPControl **ctrlp ) 445{ 446 LDAPControl *ctrl; 447 448 assert( requestOID != NULL ); 449 assert( ctrlp != NULL ); 450 451 ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) ); 452 if ( ctrl == NULL ) { 453 return LDAP_NO_MEMORY; 454 } 455 456 BER_BVZERO(&ctrl->ldctl_value); 457 if ( ber && ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 )) { 458 LDAP_FREE( ctrl ); 459 return LDAP_NO_MEMORY; 460 } 461 462 ctrl->ldctl_oid = LDAP_STRDUP( requestOID ); 463 ctrl->ldctl_iscritical = iscritical; 464 465 if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) { 466 ldap_control_free( ctrl ); 467 return LDAP_NO_MEMORY; 468 } 469 470 *ctrlp = ctrl; 471 return LDAP_SUCCESS; 472} 473 474/* 475 * Create a LDAPControl, optionally from value 476 */ 477int 478ldap_control_create( 479 LDAP_CONST char *requestOID, 480 int iscritical, 481 struct berval *value, 482 int dupval, 483 LDAPControl **ctrlp ) 484{ 485 LDAPControl *ctrl; 486 487 assert( requestOID != NULL ); 488 assert( ctrlp != NULL ); 489 490 ctrl = (LDAPControl *) LDAP_CALLOC( sizeof(LDAPControl), 1 ); 491 if ( ctrl == NULL ) { 492 return LDAP_NO_MEMORY; 493 } 494 495 ctrl->ldctl_iscritical = iscritical; 496 if ( requestOID != NULL ) { 497 ctrl->ldctl_oid = LDAP_STRDUP( requestOID ); 498 if ( ctrl->ldctl_oid == NULL ) { 499 ldap_control_free( ctrl ); 500 return LDAP_NO_MEMORY; 501 } 502 } 503 504 if ( value && !BER_BVISNULL( value ) ) { 505 if ( dupval ) { 506 ber_dupbv( &ctrl->ldctl_value, value ); 507 if ( BER_BVISNULL( &ctrl->ldctl_value ) ) { 508 ldap_control_free( ctrl ); 509 return LDAP_NO_MEMORY; 510 } 511 512 } else { 513 ctrl->ldctl_value = *value; 514 } 515 } 516 517 *ctrlp = ctrl; 518 519 return LDAP_SUCCESS; 520} 521 522/* 523 * check for critical client controls and bitch if present 524 * if we ever support critical controls, we'll have to 525 * find a means for maintaining per API call control 526 * information. 527 */ 528int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls ) 529{ 530 LDAPControl *const *c; 531 532 assert( ld != NULL ); 533 assert( LDAP_VALID( ld ) ); 534 535 if( ctrls == NULL ) { 536 /* use default server controls */ 537 ctrls = ld->ld_cctrls; 538 } 539 540 if( ctrls == NULL || *ctrls == NULL ) { 541 return LDAP_SUCCESS; 542 } 543 544 for( c = ctrls ; *c != NULL; c++ ) { 545 if( (*c)->ldctl_iscritical ) { 546 ld->ld_errno = LDAP_NOT_SUPPORTED; 547 return ld->ld_errno; 548 } 549 } 550 551 return LDAP_SUCCESS; 552} 553