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