1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 7 #pragma ident "%Z%%M% %I% %E% SMI" 8 9 10 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 11 * 12 * The contents of this file are subject to the Netscape Public License 13 * Version 1.0 (the "NPL"); you may not use this file except in 14 * compliance with the NPL. You may obtain a copy of the NPL at 15 * http://www.mozilla.org/NPL/ 16 * 17 * Software distributed under the NPL is distributed on an "AS IS" basis, 18 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL 19 * for the specific language governing rights and limitations under the 20 * NPL. 21 * 22 * The Initial Developer of this code under the NPL is Netscape 23 * Communications Corporation. Portions created by Netscape are 24 * Copyright (C) 1998 Netscape Communications Corporation. All Rights 25 * Reserved. 26 */ 27 28 /* 29 * Copyright (c) 1990 Regents of the University of Michigan. 30 * All rights reserved. 31 * 32 * Redistribution and use in source and binary forms are permitted 33 * provided that this notice is preserved and that due credit is given 34 * to the University of Michigan at Ann Arbor. The name of the University 35 * may not be used to endorse or promote products derived from this 36 * software without specific prior written permission. This software 37 * is provided ``as is'' without express or implied warranty. 38 */ 39 /* io.c - ber general i/o routines */ 40 41 #include "lber-int.h" 42 43 #define bergetc( sb, len ) ( sb->sb_ber.ber_end > sb->sb_ber.ber_ptr ? \ 44 (unsigned char)*sb->sb_ber.ber_ptr++ : \ 45 ber_filbuf( sb, len )) 46 47 # ifdef macintosh 48 /* 49 * MacTCP/OpenTransport 50 */ 51 # define read( s, b, l ) tcpread( s, 0, (unsigned char *)b, l, NULL ) 52 # define MAX_WRITE 65535 53 # define BerWrite( sb, b, l ) tcpwrite( sb->sb_sd, (unsigned char *)(b), (l<MAX_WRITE)? l : MAX_WRITE ) 54 # else /* macintosh */ 55 # if defined(_WIN32) || defined(_WINDOWS) || defined(XP_OS2) 56 /* 57 * 32-bit Windows Socket API (under Windows NT or Windows 95) 58 */ 59 # define read( s, b, l ) recv( s, b, l, 0 ) 60 # define BerWrite( s, b, l ) send( s->sb_sd, b, l, 0 ) 61 # else /* _WIN32 */ 62 /* 63 * everything else (Unix/BSD 4.3 socket API) 64 */ 65 # define BerWrite( sb, b, l ) write( sb->sb_sd, b, l ) 66 # define udp_read( sb, b, l, al ) recvfrom(sb->sb_sd, (char *)b, l, 0, \ 67 (struct sockaddr *)sb->sb_fromaddr, \ 68 (al = sizeof(struct sockaddr), &al)) 69 # define udp_write( sb, b, l ) sendto(sb->sb_sd, (char *)(b), l, 0, \ 70 (struct sockaddr *)sb->sb_useaddr, sizeof(struct sockaddr)) 71 # endif /* _WIN32 */ 72 # endif /* macintosh */ 73 74 #ifndef udp_read 75 #define udp_read( sb, b, l, al ) CLDAP NOT SUPPORTED 76 #define udp_write( sb, b, l ) CLDAP NOT SUPPORTED 77 #endif /* udp_read */ 78 79 #define EXBUFSIZ 1024 80 81 #ifdef LDAP_DEBUG 82 int lber_debug; 83 #endif 84 85 /* 86 * function prototypes 87 */ 88 static void nslberi_install_compat_io_fns( Sockbuf *sb ); 89 static int nslberi_extread_compat( int s, void *buf, int len, 90 struct lextiof_socket_private *arg ); 91 static int nslberi_extwrite_compat( int s, const void *buf, int len, 92 struct lextiof_socket_private *arg ); 93 94 95 /* 96 * internal global structure for memory allocation callback functions 97 */ 98 static struct lber_memalloc_fns nslberi_memalloc_fns; 99 100 101 /* 102 * buffered read from "sb". 103 * returns value of first character read on success and -1 on error. 104 */ 105 static int 106 ber_filbuf( Sockbuf *sb, ber_slen_t len ) 107 { 108 ssize_t rc; 109 #ifdef CLDAP 110 int addrlen; 111 #endif /* CLDAP */ 112 113 if ( sb->sb_ber.ber_buf == NULL ) { 114 if ( (sb->sb_ber.ber_buf = (char *)NSLBERI_MALLOC( 115 READBUFSIZ )) == NULL ) { 116 return( -1 ); 117 } 118 sb->sb_ber.ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; 119 sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf; 120 sb->sb_ber.ber_end = sb->sb_ber.ber_buf; 121 } 122 123 if ( sb->sb_naddr > 0 ) { 124 #ifdef CLDAP 125 rc = udp_read(sb, sb->sb_ber.ber_buf, READBUFSIZ, addrlen ); 126 #ifdef LDAP_DEBUG 127 if ( lber_debug ) { 128 char msg[80]; 129 sprintf( msg, "ber_filbuf udp_read %d bytes\n", 130 rc ); 131 ber_err_print( msg ); 132 if ( lber_debug > 1 && rc > 0 ) 133 lber_bprint( sb->sb_ber.ber_buf, rc ); 134 } 135 #endif /* LDAP_DEBUG */ 136 #else /* CLDAP */ 137 rc = -1; 138 #endif /* CLDAP */ 139 } else { 140 if ( sb->sb_ext_io_fns.lbextiofn_read != NULL ) { 141 rc = sb->sb_ext_io_fns.lbextiofn_read( 142 sb->sb_sd, sb->sb_ber.ber_buf, 143 ((sb->sb_options & LBER_SOCKBUF_OPT_NO_READ_AHEAD) 144 && (len < READBUFSIZ)) ? len : READBUFSIZ, 145 sb->sb_ext_io_fns.lbextiofn_socket_arg ); 146 } else { 147 rc = read( sb->sb_sd, sb->sb_ber.ber_buf, 148 ((sb->sb_options & LBER_SOCKBUF_OPT_NO_READ_AHEAD) 149 && (len < READBUFSIZ)) ? len : READBUFSIZ ); 150 } 151 } 152 153 if ( rc > 0 ) { 154 sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf + 1; 155 sb->sb_ber.ber_end = sb->sb_ber.ber_buf + rc; 156 return( (unsigned char)*sb->sb_ber.ber_buf ); 157 } 158 159 return( -1 ); 160 } 161 162 163 static ber_int_t 164 BerRead( Sockbuf *sb, char *buf, ber_slen_t len ) 165 { 166 int c; 167 ber_int_t nread = 0; 168 169 while ( len > 0 ) { 170 if ( (c = bergetc( sb, len )) < 0 ) { 171 if ( nread > 0 ) 172 break; 173 return( c ); 174 } 175 *buf++ = c; 176 nread++; 177 len--; 178 } 179 180 return( nread ); 181 } 182 183 184 /* 185 * Note: ber_read() only uses the ber_end and ber_ptr elements of ber. 186 * Functions like ber_get_tag(), ber_skip_tag, and ber_peek_tag() rely on 187 * that fact, so if this code is changed to use any additional elements of 188 * the ber structure, those functions will need to be changed as well. 189 */ 190 ber_int_t 191 LDAP_CALL 192 ber_read( BerElement *ber, char *buf, ber_len_t len ) 193 { 194 ber_len_t actuallen; 195 ber_uint_t nleft; 196 197 nleft = ber->ber_end - ber->ber_ptr; 198 actuallen = nleft < len ? nleft : len; 199 200 SAFEMEMCPY( buf, ber->ber_ptr, (size_t)actuallen ); 201 202 ber->ber_ptr += actuallen; 203 204 return( (ber_int_t)actuallen ); 205 } 206 207 /* 208 * enlarge the ber buffer. 209 * return 0 on success, -1 on error. 210 */ 211 int 212 nslberi_ber_realloc( BerElement *ber, ber_len_t len ) 213 { 214 ber_uint_t need, have, total; 215 size_t have_bytes; 216 Seqorset *s; 217 ber_int_t off; 218 char *oldbuf; 219 220 have_bytes = ber->ber_end - ber->ber_buf; 221 have = have_bytes / EXBUFSIZ; 222 need = (len < EXBUFSIZ ? 1 : (len + (EXBUFSIZ - 1)) / EXBUFSIZ); 223 total = have * EXBUFSIZ + need * EXBUFSIZ; 224 225 oldbuf = ber->ber_buf; 226 227 if (ber->ber_buf == NULL) { 228 if ( (ber->ber_buf = (char *)NSLBERI_MALLOC( (size_t)total )) 229 == NULL ) { 230 return( -1 ); 231 } 232 ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; 233 } else { 234 if ( ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER ) { 235 /* transition to malloc'd buffer */ 236 if ( (ber->ber_buf = (char *)NSLBERI_MALLOC( 237 (size_t)total )) == NULL ) { 238 return( -1 ); 239 } 240 ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; 241 /* copy existing data into new malloc'd buffer */ 242 SAFEMEMCPY( ber->ber_buf, oldbuf, have_bytes ); 243 } else { 244 if ( (ber->ber_buf = (char *)NSLBERI_REALLOC( 245 ber->ber_buf,(size_t)total )) == NULL ) { 246 return( -1 ); 247 } 248 } 249 } 250 251 ber->ber_end = ber->ber_buf + total; 252 253 /* 254 * If the stinking thing was moved, we need to go through and 255 * reset all the sos and ber pointers. Offsets would've been 256 * a better idea... oh well. 257 */ 258 259 if ( ber->ber_buf != oldbuf ) { 260 ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf); 261 262 for ( s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next ) { 263 off = s->sos_first - oldbuf; 264 s->sos_first = ber->ber_buf + off; 265 266 off = s->sos_ptr - oldbuf; 267 s->sos_ptr = ber->ber_buf + off; 268 } 269 } 270 271 return( 0 ); 272 } 273 274 /* 275 * returns "len" on success and -1 on failure. 276 */ 277 ber_int_t 278 LDAP_CALL 279 ber_write( BerElement *ber, char *buf, ber_len_t len, int nosos ) 280 { 281 if ( nosos || ber->ber_sos == NULL ) { 282 if ( ber->ber_ptr + len > ber->ber_end ) { 283 if ( nslberi_ber_realloc( ber, len ) != 0 ) 284 return( -1 ); 285 } 286 SAFEMEMCPY( ber->ber_ptr, buf, (size_t)len ); 287 ber->ber_ptr += len; 288 return( len ); 289 } else { 290 if ( ber->ber_sos->sos_ptr + len > ber->ber_end ) { 291 if ( nslberi_ber_realloc( ber, len ) != 0 ) 292 return( -1 ); 293 } 294 SAFEMEMCPY( ber->ber_sos->sos_ptr, buf, (size_t)len ); 295 ber->ber_sos->sos_ptr += len; 296 ber->ber_sos->sos_clen += len; 297 return( len ); 298 } 299 } 300 301 void 302 LDAP_CALL 303 ber_free( BerElement *ber, int freebuf ) 304 { 305 if ( ber != NULL ) { 306 if ( freebuf && 307 !(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) { 308 NSLBERI_FREE(ber->ber_buf); 309 } 310 NSLBERI_FREE( (char *) ber ); 311 } 312 } 313 314 /* 315 * return >= 0 on success, -1 on failure. 316 */ 317 int 318 LDAP_CALL 319 ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) 320 { 321 ssize_t nwritten, towrite, rc; 322 323 if ( ber->ber_rwptr == NULL ) { 324 ber->ber_rwptr = ber->ber_buf; 325 } else if (ber->ber_rwptr >= ber->ber_end) { 326 /* we will use the ber_rwptr to continue an exited flush, 327 so if rwptr is not within the buffer we return an error. */ 328 return( -1 ); 329 } 330 towrite = ber->ber_ptr - ber->ber_rwptr; 331 332 #ifdef LDAP_DEBUG 333 if ( lber_debug ) { 334 char msg[80]; 335 sprintf( msg, "ber_flush: %ld bytes to sd %ld%s\n", towrite, 336 sb->sb_sd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)" 337 : "" ); 338 ber_err_print( msg ); 339 if ( lber_debug > 1 ) 340 lber_bprint( ber->ber_rwptr, towrite ); 341 } 342 #endif 343 #if !defined(macintosh) && !defined(DOS) 344 if ( sb->sb_options & (LBER_SOCKBUF_OPT_TO_FILE | LBER_SOCKBUF_OPT_TO_FILE_ONLY) ) { 345 rc = write( sb->sb_copyfd, ber->ber_buf, towrite ); 346 if ( sb->sb_options & LBER_SOCKBUF_OPT_TO_FILE_ONLY ) { 347 return( (int)rc ); 348 } 349 } 350 #endif 351 352 nwritten = 0; 353 do { 354 if (sb->sb_naddr > 0) { 355 #ifdef CLDAP 356 rc = udp_write( sb, ber->ber_buf + nwritten, 357 (size_t)towrite ); 358 #else /* CLDAP */ 359 rc = -1; 360 #endif /* CLDAP */ 361 if ( rc <= 0 ) 362 return( -1 ); 363 /* fake error if write was not atomic */ 364 if (rc < towrite) { 365 #if !defined( macintosh ) && !defined( DOS ) 366 errno = EMSGSIZE; /* For Win32, see portable.h */ 367 #endif 368 return( -1 ); 369 } 370 } else { 371 if ( sb->sb_ext_io_fns.lbextiofn_write != NULL ) { 372 if ( (rc = sb->sb_ext_io_fns.lbextiofn_write( 373 sb->sb_sd, ber->ber_rwptr, (size_t)towrite, 374 sb->sb_ext_io_fns.lbextiofn_socket_arg )) 375 <= 0 ) { 376 return( -1 ); 377 } 378 } else { 379 if ( (rc = BerWrite( sb, ber->ber_rwptr, 380 (size_t) towrite )) <= 0 ) { 381 return( -1 ); 382 } 383 } 384 } 385 towrite -= rc; 386 nwritten += rc; 387 ber->ber_rwptr += rc; 388 } while ( towrite > 0 ); 389 390 if ( freeit ) 391 ber_free( ber, 1 ); 392 393 return( 0 ); 394 } 395 396 397 /* we pre-allocate a buffer to save the extra malloc later */ 398 BerElement * 399 LDAP_CALL 400 ber_alloc_t( int options ) 401 { 402 BerElement *ber; 403 404 if ( (ber = (BerElement*)NSLBERI_CALLOC( 1, 405 sizeof(struct berelement) + EXBUFSIZ )) == NULL ) { 406 return( NULL ); 407 } 408 409 /* 410 * for compatibility with the C LDAP API standard, we recognize 411 * LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info. 412 */ 413 if ( options & LBER_USE_DER ) { 414 options &= ~LBER_USE_DER; 415 options |= LBER_OPT_USE_DER; 416 } 417 418 ber->ber_tag = LBER_DEFAULT; 419 ber->ber_options = options; 420 ber->ber_buf = (char*)ber + sizeof(struct berelement); 421 ber->ber_ptr = ber->ber_buf; 422 ber->ber_end = ber->ber_buf + EXBUFSIZ; 423 ber->ber_flags = LBER_FLAG_NO_FREE_BUFFER; 424 425 return( ber ); 426 } 427 428 429 BerElement * 430 LDAP_CALL 431 ber_alloc() 432 { 433 return( ber_alloc_t( 0 ) ); 434 } 435 436 BerElement * 437 LDAP_CALL 438 der_alloc() 439 { 440 return( ber_alloc_t( LBER_OPT_USE_DER ) ); 441 } 442 443 BerElement * 444 LDAP_CALL 445 ber_dup( BerElement *ber ) 446 { 447 BerElement *new; 448 449 if ( (new = ber_alloc()) == NULL ) 450 return( NULL ); 451 452 *new = *ber; 453 454 return( new ); 455 } 456 457 458 void 459 LDAP_CALL 460 ber_init_w_nullchar( BerElement *ber, int options ) 461 { 462 (void) memset( (char *)ber, '\0', sizeof(struct berelement) ); 463 ber->ber_tag = LBER_DEFAULT; 464 465 /* 466 * For compatibility with the C LDAP API standard, we recognize 467 * LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info. 468 */ 469 if ( options & LBER_USE_DER ) { 470 options &= ~LBER_USE_DER; 471 options |= LBER_OPT_USE_DER; 472 } 473 474 ber->ber_options = options; 475 } 476 477 478 void 479 LDAP_CALL 480 ber_reset( BerElement *ber, int was_writing ) 481 { 482 if ( was_writing ) { 483 ber->ber_end = ber->ber_ptr; 484 ber->ber_ptr = ber->ber_buf; 485 } else { 486 ber->ber_ptr = ber->ber_end; 487 } 488 489 ber->ber_rwptr = NULL; 490 } 491 492 493 #ifdef LDAP_DEBUG 494 495 void 496 ber_dump( BerElement *ber, int inout ) 497 { 498 char msg[128]; 499 sprintf( msg, "ber_dump: buf 0x%lx, ptr 0x%lx, rwptr 0x%lx, end 0x%lx\n", 500 ber->ber_buf, ber->ber_ptr, ber->ber_rwptr, ber->ber_end ); 501 ber_err_print( msg ); 502 if ( inout == 1 ) { 503 sprintf( msg, " current len %ld, contents:\n", 504 ber->ber_end - ber->ber_ptr ); 505 ber_err_print( msg ); 506 lber_bprint( ber->ber_ptr, ber->ber_end - ber->ber_ptr ); 507 } else { 508 sprintf( msg, " current len %ld, contents:\n", 509 ber->ber_ptr - ber->ber_buf ); 510 ber_err_print( msg ); 511 lber_bprint( ber->ber_buf, ber->ber_ptr - ber->ber_buf ); 512 } 513 } 514 515 void 516 ber_sos_dump( Seqorset *sos ) 517 { 518 char msg[80]; 519 ber_err_print ( "*** sos dump ***\n" ); 520 while ( sos != NULLSEQORSET ) { 521 sprintf( msg, "ber_sos_dump: clen %ld first 0x%lx ptr 0x%lx\n", 522 sos->sos_clen, sos->sos_first, sos->sos_ptr ); 523 ber_err_print( msg ); 524 sprintf( msg, " current len %ld contents:\n", 525 sos->sos_ptr - sos->sos_first ); 526 ber_err_print( msg ); 527 lber_bprint( sos->sos_first, sos->sos_ptr - sos->sos_first ); 528 529 sos = sos->sos_next; 530 } 531 ber_err_print( "*** end dump ***\n" ); 532 } 533 534 #endif 535 536 /* return the tag - LBER_DEFAULT returned means trouble */ 537 static ber_tag_t 538 get_tag( Sockbuf *sb ) 539 { 540 unsigned char xbyte; 541 ber_tag_t tag; 542 char *tagp; 543 int i; 544 545 if ( (i = BerRead( sb, (char *) &xbyte, 1 )) != 1 ) { 546 return( LBER_DEFAULT ); 547 } 548 549 if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) { 550 return( (ber_uint_t) xbyte ); 551 } 552 553 tagp = (char *) &tag; 554 tagp[0] = xbyte; 555 for ( i = 1; i < sizeof(ber_int_t); i++ ) { 556 if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 ) 557 return( LBER_DEFAULT ); 558 559 tagp[i] = xbyte; 560 561 if ( ! (xbyte & LBER_MORE_TAG_MASK) ) 562 break; 563 } 564 565 /* tag too big! */ 566 if ( i == sizeof(ber_int_t) ) 567 return( LBER_DEFAULT ); 568 569 /* want leading, not trailing 0's */ 570 return( tag >> (sizeof(ber_int_t) - i - 1) ); 571 } 572 573 ber_tag_t 574 LDAP_CALL 575 ber_get_next( Sockbuf *sb, ber_len_t *len, BerElement *ber ) 576 { 577 ber_tag_t tag = 0; 578 ber_len_t netlen; 579 ber_uint_t toread; 580 unsigned char lc; 581 ber_int_t rc; 582 int noctets, diff; 583 584 #ifdef LDAP_DEBUG 585 if ( lber_debug ) 586 ber_err_print( "ber_get_next\n" ); 587 #endif 588 589 /* 590 * Any ber element looks like this: tag length contents. 591 * Assuming everything's ok, we return the tag byte (we 592 * can assume a single byte), return the length in len, 593 * and the rest of the undecoded element in buf. 594 * 595 * Assumptions: 596 * 1) small tags (less than 128) 597 * 2) definite lengths 598 * 3) primitive encodings used whenever possible 599 */ 600 601 /* 602 * first time through - malloc the buffer, set up ptrs, and 603 * read the tag and the length and as much of the rest as we can 604 */ 605 606 if ( ber->ber_rwptr == NULL ) { 607 /* 608 * First, we read the tag. 609 */ 610 611 if ( (tag = get_tag( sb )) == LBER_DEFAULT ) { 612 return( LBER_DEFAULT ); 613 } 614 ber->ber_tag = tag; 615 616 /* 617 * Next, read the length. The first byte contains the length 618 * of the length. If bit 8 is set, the length is the long 619 * form, otherwise it's the short form. We don't allow a 620 * length that's greater than what we can hold in an unsigned 621 * long. 622 */ 623 624 *len = netlen = 0; 625 if ( BerRead( sb, (char *) &lc, 1 ) != 1 ) { 626 return( LBER_DEFAULT ); 627 } 628 if ( lc & 0x80 ) { 629 noctets = (lc & 0x7f); 630 if ( noctets > sizeof(ber_uint_t) ) 631 return( LBER_DEFAULT ); 632 diff = sizeof(ber_uint_t) - noctets; 633 if ( BerRead( sb, (char *) &netlen + diff, noctets ) != 634 noctets ) { 635 return( LBER_DEFAULT ); 636 } 637 *len = LBER_NTOHL( netlen ); 638 } else { 639 *len = lc; 640 } 641 ber->ber_len = *len; 642 643 /* 644 * Finally, malloc a buffer for the contents and read it in. 645 * It's this buffer that's passed to all the other ber decoding 646 * routines. 647 */ 648 649 #if defined( DOS ) && !( defined( _WIN32 ) || defined(XP_OS2) ) 650 if ( *len > 65535 ) { /* DOS can't allocate > 64K */ 651 return( LBER_DEFAULT ); 652 } 653 #endif /* DOS && !_WIN32 */ 654 655 if ( ( sb->sb_options & LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE ) 656 && *len > sb->sb_max_incoming ) { 657 return( LBER_DEFAULT ); 658 } 659 660 if ( (ber->ber_buf = (char *)NSLBERI_CALLOC( 1,(size_t)*len )) 661 == NULL ) { 662 return( LBER_DEFAULT ); 663 } 664 ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; 665 ber->ber_ptr = ber->ber_buf; 666 ber->ber_end = ber->ber_buf + *len; 667 ber->ber_rwptr = ber->ber_buf; 668 } 669 670 toread = (uintptr_t)ber->ber_end - (uintptr_t)ber->ber_rwptr; 671 do { 672 if ( (rc = BerRead( sb, ber->ber_rwptr, (ber_int_t)toread )) <= 0 ) { 673 return( LBER_DEFAULT ); 674 } 675 676 toread -= rc; 677 ber->ber_rwptr += rc; 678 } while ( toread > 0 ); 679 680 #ifdef LDAP_DEBUG 681 if ( lber_debug ) { 682 char msg[80]; 683 sprintf( msg, "ber_get_next: tag 0x%lx len %ld contents:\n", 684 tag, ber->ber_len ); 685 ber_err_print( msg ); 686 if ( lber_debug > 1 ) 687 ber_dump( ber, 1 ); 688 } 689 #endif 690 691 *len = ber->ber_len; 692 ber->ber_rwptr = NULL; 693 return( ber->ber_tag ); 694 } 695 696 Sockbuf * 697 LDAP_CALL 698 ber_sockbuf_alloc() 699 { 700 return( (Sockbuf *)NSLBERI_CALLOC( 1, sizeof(struct sockbuf) ) ); 701 } 702 703 void 704 LDAP_CALL 705 ber_sockbuf_free(Sockbuf *p) 706 { 707 if ( p != NULL ) { 708 if ( p->sb_ber.ber_buf != NULL && 709 !(p->sb_ber.ber_flags & LBER_FLAG_NO_FREE_BUFFER) ) { 710 NSLBERI_FREE( p->sb_ber.ber_buf ); 711 } 712 NSLBERI_FREE(p); 713 } 714 } 715 716 /* 717 * return 0 on success and -1 on error 718 */ 719 int 720 LDAP_CALL 721 ber_set_option( struct berelement *ber, int option, void *value ) 722 { 723 724 /* 725 * memory allocation callbacks are global, so it is OK to pass 726 * NULL for ber. Handle this as a special case. 727 */ 728 if ( option == LBER_OPT_MEMALLOC_FN_PTRS ) { 729 /* struct copy */ 730 nslberi_memalloc_fns = *((struct lber_memalloc_fns *)value); 731 return( 0 ); 732 } 733 734 /* 735 * lber_debug is global, so it is OK to pass 736 * NULL for ber. Handle this as a special case. 737 */ 738 if ( option == LBER_OPT_DEBUG_LEVEL ) { 739 #ifdef LDAP_DEBUG 740 lber_debug = *(int *)value; 741 #endif 742 return( 0 ); 743 } 744 745 /* 746 * all the rest require a non-NULL ber 747 */ 748 if ( !NSLBERI_VALID_BERELEMENT_POINTER( ber )) { 749 return( -1 ); 750 } 751 752 switch ( option ) { 753 case LBER_OPT_USE_DER: 754 case LBER_OPT_TRANSLATE_STRINGS: 755 if ( value != NULL ) { 756 ber->ber_options |= option; 757 } else { 758 ber->ber_options &= ~option; 759 } 760 break; 761 case LBER_OPT_REMAINING_BYTES: 762 ber->ber_end = ber->ber_ptr + *((ber_uint_t *)value); 763 break; 764 case LBER_OPT_TOTAL_BYTES: 765 ber->ber_end = ber->ber_buf + *((ber_uint_t *)value); 766 break; 767 case LBER_OPT_BYTES_TO_WRITE: 768 ber->ber_ptr = ber->ber_buf + *((ber_uint_t *)value); 769 break; 770 default: 771 return( -1 ); 772 } 773 774 return( 0 ); 775 } 776 777 /* 778 * return 0 on success and -1 on error 779 */ 780 int 781 LDAP_CALL 782 ber_get_option( struct berelement *ber, int option, void *value ) 783 { 784 /* 785 * memory callocation callbacks are global, so it is OK to pass 786 * NULL for ber. Handle this as a special case 787 */ 788 if ( option == LBER_OPT_MEMALLOC_FN_PTRS ) { 789 /* struct copy */ 790 *((struct lber_memalloc_fns *)value) = nslberi_memalloc_fns; 791 return( 0 ); 792 } 793 794 /* 795 * lber_debug is global, so it is OK to pass 796 * NULL for ber. Handle this as a special case. 797 */ 798 if ( option == LBER_OPT_DEBUG_LEVEL ) { 799 #ifdef LDAP_DEBUG 800 *(int *)value = lber_debug; 801 #endif 802 return( 0 ); 803 } 804 /* 805 * all the rest require a non-NULL ber 806 */ 807 if ( !NSLBERI_VALID_BERELEMENT_POINTER( ber )) { 808 return( -1 ); 809 } 810 811 switch ( option ) { 812 case LBER_OPT_USE_DER: 813 case LBER_OPT_TRANSLATE_STRINGS: 814 *((int *) value) = (ber->ber_options & option); 815 break; 816 case LBER_OPT_REMAINING_BYTES: 817 *((ber_uint_t *) value) = ber->ber_end - ber->ber_ptr; 818 break; 819 case LBER_OPT_TOTAL_BYTES: 820 *((ber_uint_t *) value) = ber->ber_end - ber->ber_buf; 821 break; 822 case LBER_OPT_BYTES_TO_WRITE: 823 *((ber_uint_t *) value) = ber->ber_ptr - ber->ber_buf; 824 break; 825 default: 826 return( -1 ); 827 } 828 829 return( 0 ); 830 } 831 832 /* 833 * return 0 on success and -1 on error 834 */ 835 int 836 LDAP_CALL 837 ber_sockbuf_set_option( Sockbuf *sb, int option, void *value ) 838 { 839 struct lber_x_ext_io_fns *extiofns; 840 841 if ( !NSLBERI_VALID_SOCKBUF_POINTER( sb )) { 842 return( -1 ); 843 } 844 845 switch ( option ) { 846 case LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE: 847 sb->sb_max_incoming = *((ber_uint_t *) value); 848 /* FALL */ 849 case LBER_SOCKBUF_OPT_TO_FILE: 850 case LBER_SOCKBUF_OPT_TO_FILE_ONLY: 851 case LBER_SOCKBUF_OPT_NO_READ_AHEAD: 852 if ( value != NULL ) { 853 sb->sb_options |= option; 854 } else { 855 sb->sb_options &= ~option; 856 } 857 break; 858 case LBER_SOCKBUF_OPT_DESC: 859 sb->sb_sd = *((LBER_SOCKET *) value); 860 break; 861 case LBER_SOCKBUF_OPT_COPYDESC: 862 sb->sb_copyfd = *((LBER_SOCKET *) value); 863 break; 864 case LBER_SOCKBUF_OPT_READ_FN: 865 sb->sb_io_fns.lbiof_read = (LDAP_IOF_READ_CALLBACK *) value; 866 nslberi_install_compat_io_fns( sb ); 867 break; 868 case LBER_SOCKBUF_OPT_WRITE_FN: 869 sb->sb_io_fns.lbiof_write = (LDAP_IOF_WRITE_CALLBACK *) value; 870 nslberi_install_compat_io_fns( sb ); 871 break; 872 case LBER_SOCKBUF_OPT_EXT_IO_FNS: 873 extiofns = (struct lber_x_ext_io_fns *) value; 874 if ( extiofns == NULL ) { /* remove */ 875 (void)memset( (char *)&sb->sb_ext_io_fns, '\0', 876 sizeof(sb->sb_ext_io_fns )); 877 } else if ( extiofns->lbextiofn_size 878 == LBER_X_EXTIO_FNS_SIZE ) { 879 /* struct copy */ 880 sb->sb_ext_io_fns = *extiofns; 881 } else { 882 return( -1 ); 883 } 884 break; 885 default: 886 return( -1 ); 887 } 888 889 return( 0 ); 890 } 891 892 /* 893 * return 0 on success and -1 on error 894 */ 895 int 896 LDAP_CALL 897 ber_sockbuf_get_option( Sockbuf *sb, int option, void *value ) 898 { 899 struct lber_x_ext_io_fns *extiofns; 900 901 if ( !NSLBERI_VALID_SOCKBUF_POINTER( sb )) { 902 return( -1 ); 903 } 904 905 switch ( option ) { 906 case LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE: 907 *((ber_uint_t *) value) = sb->sb_max_incoming; 908 break; 909 case LBER_SOCKBUF_OPT_TO_FILE: 910 case LBER_SOCKBUF_OPT_TO_FILE_ONLY: 911 case LBER_SOCKBUF_OPT_NO_READ_AHEAD: 912 *((int *) value) = (sb->sb_options & option); 913 break; 914 case LBER_SOCKBUF_OPT_DESC: 915 *((LBER_SOCKET *) value) = sb->sb_sd; 916 break; 917 case LBER_SOCKBUF_OPT_COPYDESC: 918 *((LBER_SOCKET *) value) = sb->sb_copyfd; 919 break; 920 case LBER_SOCKBUF_OPT_READ_FN: 921 *((LDAP_IOF_READ_CALLBACK **) value) 922 = sb->sb_io_fns.lbiof_read; 923 break; 924 case LBER_SOCKBUF_OPT_WRITE_FN: 925 *((LDAP_IOF_WRITE_CALLBACK **) value) 926 = sb->sb_io_fns.lbiof_write; 927 break; 928 case LBER_SOCKBUF_OPT_EXT_IO_FNS: 929 extiofns = (struct lber_x_ext_io_fns *) value; 930 if ( extiofns == NULL || extiofns->lbextiofn_size 931 != LBER_X_EXTIO_FNS_SIZE ) { 932 return( -1 ); 933 } 934 /* struct copy */ 935 *extiofns = sb->sb_ext_io_fns; 936 break; 937 default: 938 return( -1 ); 939 } 940 941 return( 0 ); 942 } 943 944 945 /* new dboreham code below: */ 946 947 struct byte_buffer { 948 unsigned char *p; 949 int offset; 950 int length; 951 }; 952 typedef struct byte_buffer byte_buffer; 953 954 955 /* This call allocates us a BerElement structure plus some extra memory. 956 * It returns a pointer to the BerElement, plus a pointer to the extra memory. 957 * This routine also allocates a ber data buffer within the same block, thus 958 * saving a call to calloc later when we read data. 959 */ 960 void* 961 LDAP_CALL 962 ber_special_alloc(size_t size, BerElement **ppBer) 963 { 964 char *mem = NULL; 965 966 /* Make sure mem size requested is aligned */ 967 if (0 != ( size & 0x03 )) { 968 size += (sizeof(ber_int_t) - (size & 0x03)); 969 } 970 971 mem = NSLBERI_MALLOC(sizeof(struct berelement) + EXBUFSIZ + size ); 972 if (NULL == mem) { 973 return NULL; 974 } 975 *ppBer = (BerElement*) (mem + size); 976 memset(*ppBer,0,sizeof(struct berelement)); 977 (*ppBer)->ber_tag = LBER_DEFAULT; 978 (*ppBer)->ber_buf = mem + size + sizeof(struct berelement); 979 (*ppBer)->ber_ptr = (*ppBer)->ber_buf; 980 (*ppBer)->ber_end = (*ppBer)->ber_buf + EXBUFSIZ; 981 (*ppBer)->ber_flags = LBER_FLAG_NO_FREE_BUFFER; 982 return (void*)mem; 983 } 984 985 void 986 LDAP_CALL 987 ber_special_free(void* buf, BerElement *ber) 988 { 989 if (!(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) { 990 NSLBERI_FREE(ber->ber_buf); 991 } 992 NSLBERI_FREE( buf ); 993 } 994 995 static int 996 read_bytes(byte_buffer *b, unsigned char *return_buffer, int bytes_to_read) 997 { 998 /* copy up to bytes_to_read bytes into the caller's buffer, return the number of bytes copied */ 999 int bytes_to_copy = 0; 1000 1001 if (bytes_to_read <= (b->length - b->offset) ) { 1002 bytes_to_copy = bytes_to_read; 1003 } else { 1004 bytes_to_copy = (b->length - b->offset); 1005 } 1006 if (1 == bytes_to_copy) { 1007 *return_buffer = *(b->p+b->offset++); 1008 } else 1009 if (0 == bytes_to_copy) { 1010 ; 1011 } else 1012 { 1013 memcpy(return_buffer,b->p+b->offset,bytes_to_copy); 1014 b->offset += bytes_to_copy; 1015 } 1016 return bytes_to_copy; 1017 } 1018 1019 /* return the tag - LBER_DEFAULT returned means trouble */ 1020 static ber_tag_t 1021 get_buffer_tag(byte_buffer *sb ) 1022 { 1023 unsigned char xbyte; 1024 ber_tag_t tag; 1025 char *tagp; 1026 int i; 1027 1028 if ( (i = read_bytes( sb, &xbyte, 1 )) != 1 ) { 1029 return( LBER_DEFAULT ); 1030 } 1031 1032 if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) { 1033 return( (ber_uint_t) xbyte ); 1034 } 1035 1036 tagp = (char *) &tag; 1037 tagp[0] = xbyte; 1038 for ( i = 1; i < sizeof(ber_int_t); i++ ) { 1039 if ( read_bytes( sb, &xbyte, 1 ) != 1 ) 1040 return( LBER_DEFAULT ); 1041 1042 tagp[i] = xbyte; 1043 1044 if ( ! (xbyte & LBER_MORE_TAG_MASK) ) 1045 break; 1046 } 1047 1048 /* tag too big! */ 1049 if ( i == sizeof(ber_int_t) ) 1050 return( LBER_DEFAULT ); 1051 1052 /* want leading, not trailing 0's */ 1053 return( tag >> (sizeof(ber_int_t) - i - 1) ); 1054 } 1055 1056 /* Like ber_get_next, but from a byte buffer the caller already has. */ 1057 /* Bytes_Scanned returns the number of bytes we actually looked at in the buffer. */ 1058 /* ber_get_next_buffer is now implemented in terms of ber_get_next_buffer_ext */ 1059 /* and is here for backward compatibility. This new function allows us to pass */ 1060 /* the Sockbuf structure along */ 1061 1062 ber_uint_t 1063 LDAP_CALL 1064 ber_get_next_buffer( void *buffer, size_t buffer_size, ber_len_t *len, 1065 BerElement *ber, ber_uint_t *Bytes_Scanned ) 1066 { 1067 return (ber_get_next_buffer_ext( buffer, buffer_size, len, ber, 1068 Bytes_Scanned, NULL)); 1069 } 1070 1071 ber_uint_t 1072 LDAP_CALL 1073 ber_get_next_buffer_ext( void *buffer, size_t buffer_size, ber_len_t *len, 1074 BerElement *ber, ber_uint_t *Bytes_Scanned, Sockbuf *sock ) 1075 { 1076 ber_tag_t tag = 0; 1077 ber_len_t netlen; 1078 ber_uint_t toread; 1079 unsigned char lc; 1080 ssize_t rc; 1081 int noctets, diff; 1082 byte_buffer sb = {0}; 1083 1084 1085 /* 1086 * Any ber element looks like this: tag length contents. 1087 * Assuming everything's ok, we return the tag byte (we 1088 * can assume a single byte), return the length in len, 1089 * and the rest of the undecoded element in buf. 1090 * 1091 * Assumptions: 1092 * 1) small tags (less than 128) 1093 * 2) definite lengths 1094 * 3) primitive encodings used whenever possible 1095 */ 1096 1097 /* 1098 * first time through - malloc the buffer, set up ptrs, and 1099 * read the tag and the length and as much of the rest as we can 1100 */ 1101 1102 sb.p = buffer; 1103 sb.length = buffer_size; 1104 1105 if ( ber->ber_rwptr == NULL ) { 1106 /* 1107 * First, we read the tag. 1108 */ 1109 1110 if ( (tag = get_buffer_tag( &sb )) == LBER_DEFAULT ) { 1111 goto premature_exit; 1112 } 1113 ber->ber_tag = tag; 1114 1115 /* 1116 * Next, read the length. The first byte contains the length 1117 * of the length. If bit 8 is set, the length is the long 1118 * form, otherwise it's the short form. We don't allow a 1119 * length that's greater than what we can hold in an unsigned 1120 * long. 1121 */ 1122 1123 *len = netlen = 0; 1124 if ( read_bytes( &sb, &lc, 1 ) != 1 ) { 1125 goto premature_exit; 1126 } 1127 if ( lc & 0x80 ) { 1128 noctets = (lc & 0x7f); 1129 if ( noctets > sizeof(ber_uint_t) ) 1130 goto premature_exit; 1131 diff = sizeof(ber_uint_t) - noctets; 1132 if ( read_bytes( &sb, (unsigned char *)&netlen + diff, 1133 noctets ) != noctets ) { 1134 goto premature_exit; 1135 } 1136 *len = LBER_NTOHL( netlen ); 1137 } else { 1138 *len = lc; 1139 } 1140 ber->ber_len = *len; 1141 1142 /* 1143 * Finally, malloc a buffer for the contents and read it in. 1144 * It's this buffer that's passed to all the other ber decoding 1145 * routines. 1146 */ 1147 1148 #if defined( DOS ) && !defined( _WIN32 ) 1149 if ( *len > 65535 ) { /* DOS can't allocate > 64K */ 1150 goto premature_exit; 1151 } 1152 #endif /* DOS && !_WIN32 */ 1153 1154 if ( (sock != NULL) && 1155 ( sock->sb_options & LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE ) 1156 && (*len > sock->sb_max_incoming) ) { 1157 return( LBER_DEFAULT ); 1158 } 1159 1160 if ( ber->ber_buf + *len > ber->ber_end ) { 1161 if ( nslberi_ber_realloc( ber, *len ) != 0 ) 1162 goto premature_exit; 1163 } 1164 ber->ber_ptr = ber->ber_buf; 1165 ber->ber_end = ber->ber_buf + *len; 1166 ber->ber_rwptr = ber->ber_buf; 1167 } 1168 1169 toread = (uintptr_t)ber->ber_end - (uintptr_t)ber->ber_rwptr; 1170 do { 1171 if ( (rc = read_bytes( &sb, (unsigned char *)ber->ber_rwptr, 1172 (ber_int_t)toread )) <= 0 ) { 1173 goto premature_exit; 1174 } 1175 1176 toread -= rc; 1177 ber->ber_rwptr += rc; 1178 } while ( toread > 0 ); 1179 1180 *len = ber->ber_len; 1181 *Bytes_Scanned = sb.offset; 1182 return( ber->ber_tag ); 1183 1184 premature_exit: 1185 /* 1186 * we're here because we hit the end of the buffer before seeing 1187 * all of the PDU 1188 */ 1189 *Bytes_Scanned = sb.offset; 1190 return(LBER_DEFAULT); 1191 } 1192 1193 1194 /* The ber_flatten routine allocates a struct berval whose contents 1195 * are a BER encoding taken from the ber argument. The bvPtr pointer 1196 * points to the returned berval, which must be freed using 1197 * ber_bvfree(). This routine returns 0 on success and -1 on error. 1198 * The use of ber_flatten on a BerElement in which all '{' and '}' 1199 * format modifiers have not been properly matched can result in a 1200 * berval whose contents are not a valid BER encoding. 1201 * Note that the ber_ptr is not modified. 1202 */ 1203 int 1204 LDAP_CALL 1205 ber_flatten( BerElement *ber, struct berval **bvPtr ) 1206 { 1207 struct berval *new; 1208 ber_len_t len; 1209 1210 /* allocate a struct berval */ 1211 if ( (new = (struct berval *)NSLBERI_MALLOC( sizeof(struct berval) )) 1212 == NULL ) { 1213 return( -1 ); 1214 } 1215 1216 /* 1217 * Copy everything from the BerElement's ber_buf to ber_ptr 1218 * into the berval structure. 1219 */ 1220 if ( ber == NULL ) { 1221 new->bv_val = NULL; 1222 new->bv_len = 0; 1223 } else { 1224 len = ber->ber_ptr - ber->ber_buf; 1225 if ( ( new->bv_val = (char *)NSLBERI_MALLOC( len + 1 )) == NULL ) { 1226 ber_bvfree( new ); 1227 return( -1 ); 1228 } 1229 SAFEMEMCPY( new->bv_val, ber->ber_buf, (size_t)len ); 1230 new->bv_val[len] = '\0'; 1231 new->bv_len = len; 1232 } 1233 1234 /* set bvPtr pointer to point to the returned berval */ 1235 *bvPtr = new; 1236 1237 return( 0 ); 1238 } 1239 1240 1241 /* 1242 * The ber_init function constructs and returns a new BerElement 1243 * containing a copy of the data in the bv argument. ber_init 1244 * returns the null pointer on error. 1245 */ 1246 BerElement * 1247 LDAP_CALL 1248 ber_init( const struct berval *bv ) 1249 { 1250 BerElement *ber; 1251 1252 /* construct BerElement */ 1253 if (( ber = ber_alloc_t( 0 )) != NULLBER ) { 1254 /* copy data from the bv argument into BerElement */ 1255 /* XXXmcs: had to cast unsigned long bv_len to long */ 1256 if ( (ber_write ( ber, bv->bv_val, bv->bv_len, 0 )) 1257 != (ber_slen_t)bv->bv_len ) { 1258 ber_free( ber, 1 ); 1259 return( NULL ); 1260 } 1261 } 1262 1263 /* 1264 * reset ber_ptr back to the beginning of buffer so that this new 1265 * and initialized ber element can be READ 1266 */ 1267 ber_reset( ber, 1); 1268 1269 /* 1270 * return a ptr to a new BerElement containing a copy of the data 1271 * in the bv argument or a null pointer on error 1272 */ 1273 return( ber ); 1274 } 1275 1276 1277 /* 1278 * memory allocation functions. 1279 */ 1280 void * 1281 nslberi_malloc( size_t size ) 1282 { 1283 return( nslberi_memalloc_fns.lbermem_malloc == NULL ? 1284 malloc( size ) : 1285 nslberi_memalloc_fns.lbermem_malloc( size )); 1286 } 1287 1288 1289 void * 1290 nslberi_calloc( size_t nelem, size_t elsize ) 1291 { 1292 return( nslberi_memalloc_fns.lbermem_calloc == NULL ? 1293 calloc( nelem, elsize ) : 1294 nslberi_memalloc_fns.lbermem_calloc( nelem, elsize )); 1295 } 1296 1297 1298 void * 1299 nslberi_realloc( void *ptr, size_t size ) 1300 { 1301 return( nslberi_memalloc_fns.lbermem_realloc == NULL ? 1302 realloc( ptr, size ) : 1303 nslberi_memalloc_fns.lbermem_realloc( ptr, size )); 1304 } 1305 1306 1307 void 1308 nslberi_free( void *ptr ) 1309 { 1310 if ( nslberi_memalloc_fns.lbermem_free == NULL ) { 1311 free( ptr ); 1312 } else { 1313 nslberi_memalloc_fns.lbermem_free( ptr ); 1314 } 1315 } 1316 1317 1318 /* 1319 ****************************************************************************** 1320 * functions to bridge the gap between new extended I/O functions that are 1321 * installed using ber_sockbuf_set_option( ..., LBER_SOCKBUF_OPT_EXT_IO_FNS, 1322 * ... ). 1323 * 1324 * the basic strategy is to use the new extended arg to hold a pointer to the 1325 * Sockbuf itself so we can find the old functions and call them. 1326 * note that the integer socket s passed in is not used. we use the sb_sd 1327 * from the Sockbuf itself because it is the correct type. 1328 */ 1329 static int 1330 nslberi_extread_compat( int s, void *buf, int len, 1331 struct lextiof_socket_private *arg ) 1332 { 1333 Sockbuf *sb = (Sockbuf *)arg; 1334 1335 return( sb->sb_io_fns.lbiof_read( sb->sb_sd, buf, len )); 1336 } 1337 1338 1339 static int 1340 nslberi_extwrite_compat( int s, const void *buf, int len, 1341 struct lextiof_socket_private *arg ) 1342 { 1343 Sockbuf *sb = (Sockbuf *)arg; 1344 1345 return( sb->sb_io_fns.lbiof_write( sb->sb_sd, buf, len )); 1346 } 1347 1348 1349 /* 1350 * Install I/O compatiblity functions. This can't fail. 1351 */ 1352 static void 1353 nslberi_install_compat_io_fns( Sockbuf *sb ) 1354 { 1355 sb->sb_ext_io_fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; 1356 sb->sb_ext_io_fns.lbextiofn_read = nslberi_extread_compat; 1357 sb->sb_ext_io_fns.lbextiofn_write = nslberi_extwrite_compat; 1358 sb->sb_ext_io_fns.lbextiofn_socket_arg = (void *)sb; 1359 } 1360 /* 1361 * end of compat I/O functions 1362 ****************************************************************************** 1363 */ 1364