1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
3*0Sstevel@tonic-gate * Use is subject to license terms.
4*0Sstevel@tonic-gate */
5*0Sstevel@tonic-gate
6*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
7*0Sstevel@tonic-gate
8*0Sstevel@tonic-gate /* io.c - ber general i/o routines */
9*0Sstevel@tonic-gate /*
10*0Sstevel@tonic-gate * Copyright (c) 1990 Regents of the University of Michigan.
11*0Sstevel@tonic-gate * All rights reserved.
12*0Sstevel@tonic-gate *
13*0Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted
14*0Sstevel@tonic-gate * provided that this notice is preserved and that due credit is given
15*0Sstevel@tonic-gate * to the University of Michigan at Ann Arbor. The name of the University
16*0Sstevel@tonic-gate * may not be used to endorse or promote products derived from this
17*0Sstevel@tonic-gate * software without specific prior written permission. This software
18*0Sstevel@tonic-gate * is provided ``as is'' without express or implied warranty.
19*0Sstevel@tonic-gate */
20*0Sstevel@tonic-gate
21*0Sstevel@tonic-gate #include <stdio.h>
22*0Sstevel@tonic-gate #include <ctype.h>
23*0Sstevel@tonic-gate #include <unistd.h>
24*0Sstevel@tonic-gate #include <poll.h>
25*0Sstevel@tonic-gate
26*0Sstevel@tonic-gate #if defined( DOS ) || defined( _WIN32 )
27*0Sstevel@tonic-gate #include "msdos.h"
28*0Sstevel@tonic-gate #endif /* DOS || _WIN32 */
29*0Sstevel@tonic-gate
30*0Sstevel@tonic-gate #ifdef MACOS
31*0Sstevel@tonic-gate #include <stdlib.h>
32*0Sstevel@tonic-gate #include "macos.h"
33*0Sstevel@tonic-gate #else /* MACOS */
34*0Sstevel@tonic-gate #if defined(NeXT) || defined(VMS)
35*0Sstevel@tonic-gate #include <stdlib.h>
36*0Sstevel@tonic-gate #else /* next || vms */
37*0Sstevel@tonic-gate #include <malloc.h>
38*0Sstevel@tonic-gate #endif /* next || vms */
39*0Sstevel@tonic-gate #include <errno.h>
40*0Sstevel@tonic-gate #include <sys/types.h>
41*0Sstevel@tonic-gate #include <sys/socket.h>
42*0Sstevel@tonic-gate #include <netinet/in.h>
43*0Sstevel@tonic-gate #ifdef PCNFS
44*0Sstevel@tonic-gate #include <tklib.h>
45*0Sstevel@tonic-gate #endif /* PCNFS */
46*0Sstevel@tonic-gate #endif /* MACOS */
47*0Sstevel@tonic-gate
48*0Sstevel@tonic-gate #ifdef SUN
49*0Sstevel@tonic-gate #include <unistd.h>
50*0Sstevel@tonic-gate #endif
51*0Sstevel@tonic-gate
52*0Sstevel@tonic-gate #ifndef VMS
53*0Sstevel@tonic-gate #include <memory.h>
54*0Sstevel@tonic-gate #endif
55*0Sstevel@tonic-gate #include <string.h>
56*0Sstevel@tonic-gate #include "lber.h"
57*0Sstevel@tonic-gate #include "ldap.h"
58*0Sstevel@tonic-gate #include "ldap-private.h"
59*0Sstevel@tonic-gate #include "ldap-int.h"
60*0Sstevel@tonic-gate
61*0Sstevel@tonic-gate #ifdef _WIN32
62*0Sstevel@tonic-gate #include <winsock.h>
63*0Sstevel@tonic-gate #include <io.h>
64*0Sstevel@tonic-gate #endif /* _WIN32 */
65*0Sstevel@tonic-gate
66*0Sstevel@tonic-gate #ifdef NEEDPROTOS
67*0Sstevel@tonic-gate int ber_realloc(BerElement *ber, unsigned int len);
68*0Sstevel@tonic-gate static int ber_filbuf(Sockbuf *sb, int len);
69*0Sstevel@tonic-gate static int BerRead(Sockbuf *sb, char *buf, int len);
70*0Sstevel@tonic-gate #ifdef PCNFS
71*0Sstevel@tonic-gate static int BerWrite( Sockbuf *sb, char *buf, int len );
72*0Sstevel@tonic-gate #endif /* PCNFS */
73*0Sstevel@tonic-gate #else
74*0Sstevel@tonic-gate int ber_filbuf();
75*0Sstevel@tonic-gate int BerRead();
76*0Sstevel@tonic-gate int ber_realloc();
77*0Sstevel@tonic-gate #endif /* NEEDPROTOS */
78*0Sstevel@tonic-gate
79*0Sstevel@tonic-gate #define bergetc( sb, len ) ( sb->sb_ber.ber_end > sb->sb_ber.ber_ptr ? \
80*0Sstevel@tonic-gate (unsigned char)*sb->sb_ber.ber_ptr++ : \
81*0Sstevel@tonic-gate ber_filbuf( sb, len ))
82*0Sstevel@tonic-gate
83*0Sstevel@tonic-gate #ifdef MACOS
84*0Sstevel@tonic-gate /*
85*0Sstevel@tonic-gate * MacTCP/OpenTransport
86*0Sstevel@tonic-gate */
87*0Sstevel@tonic-gate #define read( s, b, l ) tcpread( s, 0, (unsigned char *)b, l, NULL )
88*0Sstevel@tonic-gate #define MAX_WRITE 65535
89*0Sstevel@tonic-gate #define BerWrite( sb, b, l ) tcpwrite( sb->sb_sd, (unsigned char *)(b), (l<MAX_WRITE)? l : MAX_WRITE )
90*0Sstevel@tonic-gate #else /* MACOS */
91*0Sstevel@tonic-gate #ifdef DOS
92*0Sstevel@tonic-gate #ifdef PCNFS
93*0Sstevel@tonic-gate /*
94*0Sstevel@tonic-gate * PCNFS (under DOS)
95*0Sstevel@tonic-gate */
96*0Sstevel@tonic-gate #define read( s, b, l ) recv( s, b, l, 0 )
97*0Sstevel@tonic-gate #define BerWrite( s, b, l ) send( s->sb_sd, b, (int) l, 0 )
98*0Sstevel@tonic-gate #endif /* PCNFS */
99*0Sstevel@tonic-gate #ifdef NCSA
100*0Sstevel@tonic-gate /*
101*0Sstevel@tonic-gate * NCSA Telnet TCP/IP stack (under DOS)
102*0Sstevel@tonic-gate */
103*0Sstevel@tonic-gate #define read( s, b, l ) nread( s, b, l )
104*0Sstevel@tonic-gate #define BerWrite( s, b, l ) netwrite( s->sb_sd, b, l )
105*0Sstevel@tonic-gate #endif /* NCSA */
106*0Sstevel@tonic-gate #ifdef WINSOCK
107*0Sstevel@tonic-gate /*
108*0Sstevel@tonic-gate * Windows Socket API (under DOS/Windows 3.x)
109*0Sstevel@tonic-gate */
110*0Sstevel@tonic-gate #define read( s, b, l ) recv( s, b, l, 0 )
111*0Sstevel@tonic-gate #define BerWrite( s, b, l ) send( s->sb_sd, b, l, 0 )
112*0Sstevel@tonic-gate #endif /* WINSOCK */
113*0Sstevel@tonic-gate #else /* DOS */
114*0Sstevel@tonic-gate #ifdef _WIN32
115*0Sstevel@tonic-gate /*
116*0Sstevel@tonic-gate * 32-bit Windows Socket API (under Windows NT or Windows 95)
117*0Sstevel@tonic-gate */
118*0Sstevel@tonic-gate #define read( s, b, l ) recv( s, b, l, 0 )
119*0Sstevel@tonic-gate #define BerWrite( s, b, l ) send( s->sb_sd, b, l, 0 )
120*0Sstevel@tonic-gate #else /* _WIN32 */
121*0Sstevel@tonic-gate #ifdef VMS
122*0Sstevel@tonic-gate /*
123*0Sstevel@tonic-gate * VMS -- each write must be 64K or smaller
124*0Sstevel@tonic-gate */
125*0Sstevel@tonic-gate #define MAX_WRITE 65535
126*0Sstevel@tonic-gate #define BerWrite( sb, b, l ) write( sb->sb_sd, b, (l<MAX_WRITE)? l : MAX_WRITE)
127*0Sstevel@tonic-gate #else /* VMS */
128*0Sstevel@tonic-gate /*
129*0Sstevel@tonic-gate * everything else (Unix/BSD 4.3 socket API)
130*0Sstevel@tonic-gate */
131*0Sstevel@tonic-gate #define BerWrite( sb, b, l ) write( sb->sb_sd, b, l )
132*0Sstevel@tonic-gate #endif /* VMS */
133*0Sstevel@tonic-gate #define udp_read( sb, b, l, al ) recvfrom(sb->sb_sd, (char *)b, l, 0, \
134*0Sstevel@tonic-gate (struct sockaddr *)sb->sb_fromaddr, \
135*0Sstevel@tonic-gate (al = sizeof(struct sockaddr), &al))
136*0Sstevel@tonic-gate #define udp_write( sb, b, l ) sendto(sb->sb_sd, (char *)(b), l, 0, \
137*0Sstevel@tonic-gate (struct sockaddr *)sb->sb_useaddr, sizeof(struct sockaddr))
138*0Sstevel@tonic-gate #endif /* _WIN32 */
139*0Sstevel@tonic-gate #endif /* DOS */
140*0Sstevel@tonic-gate #endif /* MACOS */
141*0Sstevel@tonic-gate
142*0Sstevel@tonic-gate #ifndef udp_read
143*0Sstevel@tonic-gate #define udp_read( sb, b, l, al ) CLDAP NOT SUPPORTED
144*0Sstevel@tonic-gate #define udp_write( sb, b, l ) CLDAP NOT SUPPORTED
145*0Sstevel@tonic-gate #endif /* udp_read */
146*0Sstevel@tonic-gate
147*0Sstevel@tonic-gate #define EXBUFSIZ 1024
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gate int
ber_filbuf(Sockbuf * sb,int len)150*0Sstevel@tonic-gate ber_filbuf( Sockbuf *sb, int len )
151*0Sstevel@tonic-gate {
152*0Sstevel@tonic-gate ssize_t rc;
153*0Sstevel@tonic-gate #ifdef CLDAP
154*0Sstevel@tonic-gate int addrlen;
155*0Sstevel@tonic-gate #endif /* CLDAP */
156*0Sstevel@tonic-gate
157*0Sstevel@tonic-gate if ( sb->sb_ber.ber_buf == NULL ) {
158*0Sstevel@tonic-gate if ( (sb->sb_ber.ber_buf = (char *) malloc( READBUFSIZ )) ==
159*0Sstevel@tonic-gate NULL )
160*0Sstevel@tonic-gate return( -1 );
161*0Sstevel@tonic-gate sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf;
162*0Sstevel@tonic-gate sb->sb_ber.ber_end = sb->sb_ber.ber_buf;
163*0Sstevel@tonic-gate }
164*0Sstevel@tonic-gate
165*0Sstevel@tonic-gate if ( sb->sb_naddr > 0 ) {
166*0Sstevel@tonic-gate #ifdef CLDAP
167*0Sstevel@tonic-gate rc = udp_read(sb, sb->sb_ber.ber_buf, READBUFSIZ, addrlen );
168*0Sstevel@tonic-gate #ifdef LDAP_DEBUG
169*0Sstevel@tonic-gate if ( lber_debug ) {
170*0Sstevel@tonic-gate (void) fprintf( stderr, catgets(slapdcat, 1, 75, "ber_filbuf udp_read %d bytes\n"),
171*0Sstevel@tonic-gate (int)rc );
172*0Sstevel@tonic-gate if ( lber_debug > 1 && rc > 0 )
173*0Sstevel@tonic-gate lber_bprint( sb->sb_ber.ber_buf, (int)rc );
174*0Sstevel@tonic-gate }
175*0Sstevel@tonic-gate #endif /* LDAP_DEBUG */
176*0Sstevel@tonic-gate #else /* CLDAP */
177*0Sstevel@tonic-gate rc = -1;
178*0Sstevel@tonic-gate #endif /* CLDAP */
179*0Sstevel@tonic-gate #ifdef LDAP_SSL
180*0Sstevel@tonic-gate } else if ( sb->sb_ssl != NULL ) {
181*0Sstevel@tonic-gate rc = SSL_read(sb->sb_ssl,(u_char *)sb->sb_ber.ber_buf,
182*0Sstevel@tonic-gate ((sb->sb_options & LBER_NO_READ_AHEAD) &&
183*0Sstevel@tonic-gate (len < READBUFSIZ)) ?
184*0Sstevel@tonic-gate len : READBUFSIZ );
185*0Sstevel@tonic-gate #endif /* LDAP_SSL */
186*0Sstevel@tonic-gate } else {
187*0Sstevel@tonic-gate int loop=2;
188*0Sstevel@tonic-gate while (loop>0) {
189*0Sstevel@tonic-gate --loop;
190*0Sstevel@tonic-gate rc = read( sb->sb_sd, sb->sb_ber.ber_buf,
191*0Sstevel@tonic-gate ((sb->sb_options & LBER_NO_READ_AHEAD) &&
192*0Sstevel@tonic-gate (len < READBUFSIZ)) ?
193*0Sstevel@tonic-gate len : READBUFSIZ );
194*0Sstevel@tonic-gate /*
195*0Sstevel@tonic-gate * if packet not here yet, wait 10 seconds to let it arrive
196*0Sstevel@tonic-gate */
197*0Sstevel@tonic-gate if ( rc <= 0 && (errno==EWOULDBLOCK || errno==EAGAIN) ) {
198*0Sstevel@tonic-gate struct pollfd poll_tab[1];
199*0Sstevel@tonic-gate poll_tab[0].fd = sb->sb_sd;
200*0Sstevel@tonic-gate poll_tab[0].events = POLLIN;
201*0Sstevel@tonic-gate poll_tab[0].revents = 0;
202*0Sstevel@tonic-gate if ( poll(poll_tab, 1, 10000) <= 0) {
203*0Sstevel@tonic-gate /* nothing received or error, just abandon the read */
204*0Sstevel@tonic-gate break;
205*0Sstevel@tonic-gate } /* end if */
206*0Sstevel@tonic-gate } else {
207*0Sstevel@tonic-gate break;
208*0Sstevel@tonic-gate } /* end if */
209*0Sstevel@tonic-gate } /* end while */
210*0Sstevel@tonic-gate }
211*0Sstevel@tonic-gate
212*0Sstevel@tonic-gate if ( rc > 0 ) {
213*0Sstevel@tonic-gate sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf + 1;
214*0Sstevel@tonic-gate sb->sb_ber.ber_end = sb->sb_ber.ber_buf + rc;
215*0Sstevel@tonic-gate return( (unsigned char)*sb->sb_ber.ber_buf );
216*0Sstevel@tonic-gate }
217*0Sstevel@tonic-gate
218*0Sstevel@tonic-gate return( -1 );
219*0Sstevel@tonic-gate }
220*0Sstevel@tonic-gate
221*0Sstevel@tonic-gate
222*0Sstevel@tonic-gate int
BerRead(Sockbuf * sb,char * buf,int len)223*0Sstevel@tonic-gate BerRead( Sockbuf *sb, char *buf, int len )
224*0Sstevel@tonic-gate {
225*0Sstevel@tonic-gate int c;
226*0Sstevel@tonic-gate int nread = 0;
227*0Sstevel@tonic-gate
228*0Sstevel@tonic-gate while ( len > 0 ) {
229*0Sstevel@tonic-gate if ( (c = bergetc( sb, len )) < 0 ) {
230*0Sstevel@tonic-gate if ( nread > 0 )
231*0Sstevel@tonic-gate break;
232*0Sstevel@tonic-gate return( c );
233*0Sstevel@tonic-gate }
234*0Sstevel@tonic-gate *buf++ = (char)c;
235*0Sstevel@tonic-gate nread++;
236*0Sstevel@tonic-gate len--;
237*0Sstevel@tonic-gate }
238*0Sstevel@tonic-gate
239*0Sstevel@tonic-gate return( nread );
240*0Sstevel@tonic-gate }
241*0Sstevel@tonic-gate
242*0Sstevel@tonic-gate
243*0Sstevel@tonic-gate int
ber_read(BerElement * ber,char * buf,unsigned int len)244*0Sstevel@tonic-gate ber_read( BerElement *ber, char *buf, unsigned int len )
245*0Sstevel@tonic-gate {
246*0Sstevel@tonic-gate unsigned int actuallen, nleft;
247*0Sstevel@tonic-gate
248*0Sstevel@tonic-gate nleft = (int)(ber->ber_end - ber->ber_ptr);
249*0Sstevel@tonic-gate actuallen = nleft < len ? nleft : len;
250*0Sstevel@tonic-gate
251*0Sstevel@tonic-gate SAFEMEMCPY( buf, ber->ber_ptr, (size_t)actuallen );
252*0Sstevel@tonic-gate
253*0Sstevel@tonic-gate ber->ber_ptr += actuallen;
254*0Sstevel@tonic-gate
255*0Sstevel@tonic-gate return( (int)actuallen );
256*0Sstevel@tonic-gate }
257*0Sstevel@tonic-gate
258*0Sstevel@tonic-gate int
ber_write(BerElement * ber,char * buf,unsigned int len,int nosos)259*0Sstevel@tonic-gate ber_write( BerElement *ber, char *buf, unsigned int len, int nosos )
260*0Sstevel@tonic-gate {
261*0Sstevel@tonic-gate if ( nosos || ber->ber_sos == NULL ) {
262*0Sstevel@tonic-gate if ( ber->ber_ptr + len > ber->ber_end ) {
263*0Sstevel@tonic-gate if ( ber_realloc( ber, len ) != 0 )
264*0Sstevel@tonic-gate return( -1 );
265*0Sstevel@tonic-gate }
266*0Sstevel@tonic-gate (void) SAFEMEMCPY( ber->ber_ptr, buf, (size_t)len );
267*0Sstevel@tonic-gate ber->ber_ptr += len;
268*0Sstevel@tonic-gate return( len );
269*0Sstevel@tonic-gate } else {
270*0Sstevel@tonic-gate if ( ber->ber_sos->sos_ptr + len > ber->ber_end ) {
271*0Sstevel@tonic-gate if ( ber_realloc( ber, len ) != 0 )
272*0Sstevel@tonic-gate return( -1 );
273*0Sstevel@tonic-gate }
274*0Sstevel@tonic-gate (void) SAFEMEMCPY( ber->ber_sos->sos_ptr, buf, (size_t)len );
275*0Sstevel@tonic-gate ber->ber_sos->sos_ptr += len;
276*0Sstevel@tonic-gate ber->ber_sos->sos_clen += len;
277*0Sstevel@tonic-gate return( len );
278*0Sstevel@tonic-gate }
279*0Sstevel@tonic-gate }
280*0Sstevel@tonic-gate
281*0Sstevel@tonic-gate int
ber_realloc(BerElement * ber,unsigned int len)282*0Sstevel@tonic-gate ber_realloc(BerElement *ber, unsigned int len)
283*0Sstevel@tonic-gate {
284*0Sstevel@tonic-gate size_t need, have, total;
285*0Sstevel@tonic-gate Seqorset *s;
286*0Sstevel@tonic-gate ssize_t off;
287*0Sstevel@tonic-gate char *oldbuf;
288*0Sstevel@tonic-gate
289*0Sstevel@tonic-gate have = (ber->ber_end - ber->ber_buf) / EXBUFSIZ;
290*0Sstevel@tonic-gate need = (len < EXBUFSIZ ? 1 : (len + (EXBUFSIZ - 1)) / EXBUFSIZ);
291*0Sstevel@tonic-gate total = have * EXBUFSIZ + need * EXBUFSIZ;
292*0Sstevel@tonic-gate
293*0Sstevel@tonic-gate oldbuf = ber->ber_buf;
294*0Sstevel@tonic-gate
295*0Sstevel@tonic-gate if ( ber->ber_buf == NULL ) {
296*0Sstevel@tonic-gate if ( (ber->ber_buf = (char *) malloc( (size_t)total )) == NULL )
297*0Sstevel@tonic-gate return( -1 );
298*0Sstevel@tonic-gate } else if ( (ber->ber_buf = (char *) realloc( ber->ber_buf,
299*0Sstevel@tonic-gate (size_t)total )) == NULL )
300*0Sstevel@tonic-gate return( -1 );
301*0Sstevel@tonic-gate
302*0Sstevel@tonic-gate ber->ber_end = ber->ber_buf + total;
303*0Sstevel@tonic-gate
304*0Sstevel@tonic-gate /*
305*0Sstevel@tonic-gate * If the stinking thing was moved, we need to go through and
306*0Sstevel@tonic-gate * reset all the sos and ber pointers. Offsets would've been
307*0Sstevel@tonic-gate * a better idea... oh well.
308*0Sstevel@tonic-gate */
309*0Sstevel@tonic-gate
310*0Sstevel@tonic-gate if ( ber->ber_buf != oldbuf ) {
311*0Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf);
312*0Sstevel@tonic-gate
313*0Sstevel@tonic-gate for ( s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next ) {
314*0Sstevel@tonic-gate off = s->sos_first - oldbuf;
315*0Sstevel@tonic-gate s->sos_first = ber->ber_buf + off;
316*0Sstevel@tonic-gate
317*0Sstevel@tonic-gate off = s->sos_ptr - oldbuf;
318*0Sstevel@tonic-gate s->sos_ptr = ber->ber_buf + off;
319*0Sstevel@tonic-gate }
320*0Sstevel@tonic-gate }
321*0Sstevel@tonic-gate
322*0Sstevel@tonic-gate return( 0 );
323*0Sstevel@tonic-gate }
324*0Sstevel@tonic-gate
325*0Sstevel@tonic-gate void
ber_free(BerElement * ber,int freebuf)326*0Sstevel@tonic-gate ber_free(BerElement *ber, int freebuf)
327*0Sstevel@tonic-gate {
328*0Sstevel@tonic-gate if (NULL != ber) {
329*0Sstevel@tonic-gate if (freebuf && ber->ber_buf != NULL)
330*0Sstevel@tonic-gate free(ber->ber_buf);
331*0Sstevel@tonic-gate free((char *)ber);
332*0Sstevel@tonic-gate }
333*0Sstevel@tonic-gate }
334*0Sstevel@tonic-gate
335*0Sstevel@tonic-gate int
ber_flush(Sockbuf * sb,BerElement * ber,int freeit)336*0Sstevel@tonic-gate ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
337*0Sstevel@tonic-gate {
338*0Sstevel@tonic-gate ssize_t nwritten, towrite, rc;
339*0Sstevel@tonic-gate
340*0Sstevel@tonic-gate if ( ber->ber_rwptr == NULL ) {
341*0Sstevel@tonic-gate ber->ber_rwptr = ber->ber_buf;
342*0Sstevel@tonic-gate }
343*0Sstevel@tonic-gate towrite = ber->ber_ptr - ber->ber_rwptr;
344*0Sstevel@tonic-gate
345*0Sstevel@tonic-gate #ifdef LDAP_DEBUG
346*0Sstevel@tonic-gate if ( lber_debug ) {
347*0Sstevel@tonic-gate (void) fprintf( stderr, catgets(slapdcat, 1, 76, "ber_flush: %1$ld bytes to sd %2$ld%s\n"), towrite,
348*0Sstevel@tonic-gate sb->sb_sd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)"
349*0Sstevel@tonic-gate : "" );
350*0Sstevel@tonic-gate if ( lber_debug > 1 )
351*0Sstevel@tonic-gate lber_bprint( ber->ber_rwptr, towrite );
352*0Sstevel@tonic-gate }
353*0Sstevel@tonic-gate #endif
354*0Sstevel@tonic-gate #if !defined(MACOS) && !defined(DOS)
355*0Sstevel@tonic-gate if ( sb->sb_options & (LBER_TO_FILE | LBER_TO_FILE_ONLY) ) {
356*0Sstevel@tonic-gate #ifdef LDAP_SSL
357*0Sstevel@tonic-gate if (sb->sb_ssl) {
358*0Sstevel@tonic-gate rc = SSL_write( sb->sb_ssl, (u_char *)ber->ber_buf, towrite );
359*0Sstevel@tonic-gate if ( rc < 0 ) {
360*0Sstevel@tonic-gate fprintf( stderr, SSL_strerr(SSL_errno(sb->sb_ssl)));
361*0Sstevel@tonic-gate }
362*0Sstevel@tonic-gate } else {
363*0Sstevel@tonic-gate #endif /* LDAP_SSL */
364*0Sstevel@tonic-gate rc = write( sb->sb_fd, ber->ber_buf, towrite );
365*0Sstevel@tonic-gate if ( sb->sb_options & LBER_TO_FILE_ONLY ) {
366*0Sstevel@tonic-gate return( (int)rc );
367*0Sstevel@tonic-gate }
368*0Sstevel@tonic-gate #ifdef LDAP_SSL
369*0Sstevel@tonic-gate }
370*0Sstevel@tonic-gate #endif /* LDAP_SSL */
371*0Sstevel@tonic-gate }
372*0Sstevel@tonic-gate #endif
373*0Sstevel@tonic-gate
374*0Sstevel@tonic-gate nwritten = 0;
375*0Sstevel@tonic-gate do {
376*0Sstevel@tonic-gate if (sb->sb_naddr > 0) {
377*0Sstevel@tonic-gate #ifdef CLDAP
378*0Sstevel@tonic-gate rc = udp_write( sb, ber->ber_buf + nwritten,
379*0Sstevel@tonic-gate (size_t)towrite );
380*0Sstevel@tonic-gate #else /* CLDAP */
381*0Sstevel@tonic-gate rc = -1;
382*0Sstevel@tonic-gate #endif /* CLDAP */
383*0Sstevel@tonic-gate if ( rc <= 0 )
384*0Sstevel@tonic-gate return( -1 );
385*0Sstevel@tonic-gate /* fake error if write was not atomic */
386*0Sstevel@tonic-gate if (rc < towrite) {
387*0Sstevel@tonic-gate #if !defined( MACOS ) && !defined( DOS )
388*0Sstevel@tonic-gate errno = EMSGSIZE;
389*0Sstevel@tonic-gate #endif
390*0Sstevel@tonic-gate return( -1 );
391*0Sstevel@tonic-gate }
392*0Sstevel@tonic-gate } else {
393*0Sstevel@tonic-gate #ifdef LDAP_SSL
394*0Sstevel@tonic-gate if (sb->sb_ssl) {
395*0Sstevel@tonic-gate if ( (rc = SSL_write( sb->sb_ssl, (u_char *)ber->ber_rwptr,
396*0Sstevel@tonic-gate (size_t) towrite )) <= 0 ) {
397*0Sstevel@tonic-gate return( -1 );
398*0Sstevel@tonic-gate }
399*0Sstevel@tonic-gate } else
400*0Sstevel@tonic-gate #endif /* LDAP_SSL */
401*0Sstevel@tonic-gate if ( (rc = BerWrite( sb, ber->ber_rwptr,
402*0Sstevel@tonic-gate (size_t) towrite )) <= 0 ) {
403*0Sstevel@tonic-gate return( -1 );
404*0Sstevel@tonic-gate }
405*0Sstevel@tonic-gate }
406*0Sstevel@tonic-gate towrite -= rc;
407*0Sstevel@tonic-gate nwritten += rc;
408*0Sstevel@tonic-gate ber->ber_rwptr += rc;
409*0Sstevel@tonic-gate } while ( towrite > 0 );
410*0Sstevel@tonic-gate
411*0Sstevel@tonic-gate if ( freeit )
412*0Sstevel@tonic-gate ber_free( ber, 1 );
413*0Sstevel@tonic-gate
414*0Sstevel@tonic-gate return( 0 );
415*0Sstevel@tonic-gate }
416*0Sstevel@tonic-gate
417*0Sstevel@tonic-gate BerElement *
ber_alloc_t(int options)418*0Sstevel@tonic-gate ber_alloc_t( int options )
419*0Sstevel@tonic-gate {
420*0Sstevel@tonic-gate BerElement *ber;
421*0Sstevel@tonic-gate
422*0Sstevel@tonic-gate if ( (ber = (BerElement *) calloc( (size_t) 1, sizeof(BerElement) )) == NULLBER )
423*0Sstevel@tonic-gate return( NULLBER );
424*0Sstevel@tonic-gate ber->ber_tag = LBER_DEFAULT;
425*0Sstevel@tonic-gate ber->ber_options = (char) options;
426*0Sstevel@tonic-gate
427*0Sstevel@tonic-gate return( ber );
428*0Sstevel@tonic-gate }
429*0Sstevel@tonic-gate
430*0Sstevel@tonic-gate BerElement *
ber_alloc()431*0Sstevel@tonic-gate ber_alloc()
432*0Sstevel@tonic-gate {
433*0Sstevel@tonic-gate return( ber_alloc_t( 0 ) );
434*0Sstevel@tonic-gate }
435*0Sstevel@tonic-gate
436*0Sstevel@tonic-gate BerElement *
der_alloc()437*0Sstevel@tonic-gate der_alloc()
438*0Sstevel@tonic-gate {
439*0Sstevel@tonic-gate return( ber_alloc_t( LBER_USE_DER ) );
440*0Sstevel@tonic-gate }
441*0Sstevel@tonic-gate
442*0Sstevel@tonic-gate BerElement *
ber_dup(BerElement * ber)443*0Sstevel@tonic-gate ber_dup( BerElement *ber )
444*0Sstevel@tonic-gate {
445*0Sstevel@tonic-gate BerElement *new;
446*0Sstevel@tonic-gate
447*0Sstevel@tonic-gate if ( (new = ber_alloc()) == NULLBER )
448*0Sstevel@tonic-gate return( NULLBER );
449*0Sstevel@tonic-gate
450*0Sstevel@tonic-gate *new = *ber;
451*0Sstevel@tonic-gate
452*0Sstevel@tonic-gate return( new );
453*0Sstevel@tonic-gate }
454*0Sstevel@tonic-gate
ber_init(struct berval * bv)455*0Sstevel@tonic-gate BerElement *ber_init(struct berval *bv)
456*0Sstevel@tonic-gate {
457*0Sstevel@tonic-gate BerElement *new;
458*0Sstevel@tonic-gate
459*0Sstevel@tonic-gate if (bv == NULL)
460*0Sstevel@tonic-gate return (NULLBER);
461*0Sstevel@tonic-gate
462*0Sstevel@tonic-gate if ((new = ber_alloc()) == NULLBER)
463*0Sstevel@tonic-gate return (NULLBER);
464*0Sstevel@tonic-gate if ((new->ber_buf = (char *)malloc(bv->bv_len + 1)) == NULL){
465*0Sstevel@tonic-gate free(new);
466*0Sstevel@tonic-gate return (NULLBER);
467*0Sstevel@tonic-gate }
468*0Sstevel@tonic-gate SAFEMEMCPY(new->ber_buf, bv->bv_val, bv->bv_len);
469*0Sstevel@tonic-gate new->ber_end = new->ber_buf + bv->bv_len;
470*0Sstevel@tonic-gate new->ber_ptr = new->ber_buf;
471*0Sstevel@tonic-gate new->ber_len = bv->bv_len;
472*0Sstevel@tonic-gate return (new);
473*0Sstevel@tonic-gate }
474*0Sstevel@tonic-gate
475*0Sstevel@tonic-gate void
ber_zero_init(BerElement * ber,int options)476*0Sstevel@tonic-gate ber_zero_init( BerElement *ber, int options )
477*0Sstevel@tonic-gate {
478*0Sstevel@tonic-gate (void) memset( (char *)ber, '\0', sizeof( BerElement ));
479*0Sstevel@tonic-gate ber->ber_tag = LBER_DEFAULT;
480*0Sstevel@tonic-gate ber->ber_options = options;
481*0Sstevel@tonic-gate }
482*0Sstevel@tonic-gate
483*0Sstevel@tonic-gate
484*0Sstevel@tonic-gate void
ber_reset(BerElement * ber,int was_writing)485*0Sstevel@tonic-gate ber_reset( BerElement *ber, int was_writing )
486*0Sstevel@tonic-gate {
487*0Sstevel@tonic-gate if ( was_writing ) {
488*0Sstevel@tonic-gate ber->ber_end = ber->ber_ptr;
489*0Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf;
490*0Sstevel@tonic-gate } else {
491*0Sstevel@tonic-gate ber->ber_ptr = ber->ber_end;
492*0Sstevel@tonic-gate }
493*0Sstevel@tonic-gate
494*0Sstevel@tonic-gate ber->ber_rwptr = NULL;
495*0Sstevel@tonic-gate }
496*0Sstevel@tonic-gate
497*0Sstevel@tonic-gate
498*0Sstevel@tonic-gate #ifdef LDAP_DEBUG
499*0Sstevel@tonic-gate
500*0Sstevel@tonic-gate void
ber_dump(BerElement * ber,int inout)501*0Sstevel@tonic-gate ber_dump( BerElement *ber, int inout )
502*0Sstevel@tonic-gate {
503*0Sstevel@tonic-gate (void) fprintf( stderr, catgets(slapdcat, 1, 77, "ber_dump: buf 0x%1$lx, ptr 0x%2$lx, end 0x%3$lx\n"),
504*0Sstevel@tonic-gate ber->ber_buf, ber->ber_ptr, ber->ber_end );
505*0Sstevel@tonic-gate if ( inout == 1 ) {
506*0Sstevel@tonic-gate (void) fprintf( stderr, catgets(slapdcat, 1, 78, " current len %ld, contents:\n"),
507*0Sstevel@tonic-gate ber->ber_end - ber->ber_ptr );
508*0Sstevel@tonic-gate lber_bprint( ber->ber_ptr, ber->ber_end - ber->ber_ptr );
509*0Sstevel@tonic-gate } else {
510*0Sstevel@tonic-gate (void) fprintf( stderr, catgets(slapdcat, 1, 78, " current len %ld, contents:\n"),
511*0Sstevel@tonic-gate ber->ber_ptr - ber->ber_buf );
512*0Sstevel@tonic-gate lber_bprint( ber->ber_buf, ber->ber_ptr - ber->ber_buf );
513*0Sstevel@tonic-gate }
514*0Sstevel@tonic-gate }
515*0Sstevel@tonic-gate
516*0Sstevel@tonic-gate void
ber_sos_dump(Seqorset * sos)517*0Sstevel@tonic-gate ber_sos_dump( Seqorset *sos )
518*0Sstevel@tonic-gate {
519*0Sstevel@tonic-gate (void) fprintf( stderr, catgets(slapdcat, 1, 79, "*** sos dump ***\n") );
520*0Sstevel@tonic-gate while ( sos != NULLSEQORSET ) {
521*0Sstevel@tonic-gate (void) fprintf( stderr, catgets(slapdcat, 1, 80, "ber_sos_dump: clen %1$ld first 0x%2$lx ptr 0x%3$lx\n"),
522*0Sstevel@tonic-gate sos->sos_clen, sos->sos_first, sos->sos_ptr );
523*0Sstevel@tonic-gate (void) fprintf( stderr, catgets(slapdcat, 1, 81, " current len %ld contents:\n"),
524*0Sstevel@tonic-gate sos->sos_ptr - sos->sos_first );
525*0Sstevel@tonic-gate lber_bprint( sos->sos_first, sos->sos_ptr - sos->sos_first );
526*0Sstevel@tonic-gate
527*0Sstevel@tonic-gate sos = sos->sos_next;
528*0Sstevel@tonic-gate }
529*0Sstevel@tonic-gate (void) fprintf( stderr, catgets(slapdcat, 1, 82, "*** end dump ***\n") );
530*0Sstevel@tonic-gate }
531*0Sstevel@tonic-gate
532*0Sstevel@tonic-gate #endif
533*0Sstevel@tonic-gate
534*0Sstevel@tonic-gate /* return the tag - LBER_DEFAULT returned means trouble */
535*0Sstevel@tonic-gate static unsigned int
get_tag(Sockbuf * sb)536*0Sstevel@tonic-gate get_tag( Sockbuf *sb )
537*0Sstevel@tonic-gate {
538*0Sstevel@tonic-gate unsigned char xbyte;
539*0Sstevel@tonic-gate unsigned int tag;
540*0Sstevel@tonic-gate char *tagp;
541*0Sstevel@tonic-gate int i;
542*0Sstevel@tonic-gate
543*0Sstevel@tonic-gate if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 )
544*0Sstevel@tonic-gate return( LBER_DEFAULT );
545*0Sstevel@tonic-gate
546*0Sstevel@tonic-gate if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
547*0Sstevel@tonic-gate return( (unsigned int) xbyte );
548*0Sstevel@tonic-gate
549*0Sstevel@tonic-gate tagp = (char *) &tag;
550*0Sstevel@tonic-gate tagp[0] = xbyte;
551*0Sstevel@tonic-gate for ( i = 1; i < sizeof(int); i++ ) {
552*0Sstevel@tonic-gate if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 )
553*0Sstevel@tonic-gate return( LBER_DEFAULT );
554*0Sstevel@tonic-gate
555*0Sstevel@tonic-gate tagp[i] = xbyte;
556*0Sstevel@tonic-gate
557*0Sstevel@tonic-gate if ( ! (xbyte & LBER_MORE_TAG_MASK) )
558*0Sstevel@tonic-gate break;
559*0Sstevel@tonic-gate }
560*0Sstevel@tonic-gate
561*0Sstevel@tonic-gate /* tag too big! */
562*0Sstevel@tonic-gate if ( i == sizeof(int) )
563*0Sstevel@tonic-gate return( LBER_DEFAULT );
564*0Sstevel@tonic-gate
565*0Sstevel@tonic-gate /* want leading, not trailing 0's */
566*0Sstevel@tonic-gate return( tag >> (sizeof(int) - i - 1) );
567*0Sstevel@tonic-gate }
568*0Sstevel@tonic-gate
569*0Sstevel@tonic-gate unsigned int
ber_get_next(Sockbuf * sb,unsigned int * len,BerElement * ber)570*0Sstevel@tonic-gate ber_get_next( Sockbuf *sb, unsigned int *len, BerElement *ber )
571*0Sstevel@tonic-gate {
572*0Sstevel@tonic-gate unsigned int tag, netlen, toread;
573*0Sstevel@tonic-gate unsigned char lc;
574*0Sstevel@tonic-gate int rc;
575*0Sstevel@tonic-gate int noctets, diff;
576*0Sstevel@tonic-gate
577*0Sstevel@tonic-gate #ifdef LDAP_DEBUG
578*0Sstevel@tonic-gate if ( lber_debug )
579*0Sstevel@tonic-gate (void) fprintf( stderr, catgets(slapdcat, 1, 83, "ber_get_next\n") );
580*0Sstevel@tonic-gate #endif
581*0Sstevel@tonic-gate
582*0Sstevel@tonic-gate /*
583*0Sstevel@tonic-gate * Any ber element looks like this: tag length contents.
584*0Sstevel@tonic-gate * Assuming everything's ok, we return the tag byte (we
585*0Sstevel@tonic-gate * can assume a single byte), return the length in len,
586*0Sstevel@tonic-gate * and the rest of the undecoded element in buf.
587*0Sstevel@tonic-gate *
588*0Sstevel@tonic-gate * Assumptions:
589*0Sstevel@tonic-gate * 1) small tags (less than 128)
590*0Sstevel@tonic-gate * 2) definite lengths
591*0Sstevel@tonic-gate * 3) primitive encodings used whenever possible
592*0Sstevel@tonic-gate */
593*0Sstevel@tonic-gate
594*0Sstevel@tonic-gate /*
595*0Sstevel@tonic-gate * first time through - malloc the buffer, set up ptrs, and
596*0Sstevel@tonic-gate * read the tag and the length and as much of the rest as we can
597*0Sstevel@tonic-gate */
598*0Sstevel@tonic-gate
599*0Sstevel@tonic-gate if ( ber->ber_rwptr == NULL ) {
600*0Sstevel@tonic-gate /*
601*0Sstevel@tonic-gate * First, we read the tag.
602*0Sstevel@tonic-gate */
603*0Sstevel@tonic-gate
604*0Sstevel@tonic-gate if ( (tag = get_tag( sb )) == LBER_DEFAULT ) {
605*0Sstevel@tonic-gate return( LBER_DEFAULT );
606*0Sstevel@tonic-gate }
607*0Sstevel@tonic-gate ber->ber_tag = tag;
608*0Sstevel@tonic-gate
609*0Sstevel@tonic-gate /*
610*0Sstevel@tonic-gate * Next, read the length. The first byte contains the length
611*0Sstevel@tonic-gate * of the length. If bit 8 is set, the length is the int
612*0Sstevel@tonic-gate * form, otherwise it's the short form. We don't allow a
613*0Sstevel@tonic-gate * length that's greater than what we can hold in an unsigned
614*0Sstevel@tonic-gate * int.
615*0Sstevel@tonic-gate */
616*0Sstevel@tonic-gate
617*0Sstevel@tonic-gate *len = netlen = 0;
618*0Sstevel@tonic-gate if ( BerRead( sb, (char *) &lc, 1 ) != 1 ) {
619*0Sstevel@tonic-gate return( LBER_DEFAULT );
620*0Sstevel@tonic-gate }
621*0Sstevel@tonic-gate if ( lc & 0x80 ) {
622*0Sstevel@tonic-gate noctets = (lc & 0x7f);
623*0Sstevel@tonic-gate if ( noctets > sizeof(unsigned int) )
624*0Sstevel@tonic-gate return( LBER_DEFAULT );
625*0Sstevel@tonic-gate diff = sizeof(unsigned int) - noctets;
626*0Sstevel@tonic-gate if ( BerRead( sb, (char *) &netlen + diff, noctets ) !=
627*0Sstevel@tonic-gate noctets ) {
628*0Sstevel@tonic-gate return( LBER_DEFAULT );
629*0Sstevel@tonic-gate }
630*0Sstevel@tonic-gate *len = LBER_NTOHL( netlen );
631*0Sstevel@tonic-gate } else {
632*0Sstevel@tonic-gate *len = lc;
633*0Sstevel@tonic-gate }
634*0Sstevel@tonic-gate ber->ber_len = *len;
635*0Sstevel@tonic-gate
636*0Sstevel@tonic-gate /*
637*0Sstevel@tonic-gate * Finally, malloc a buffer for the contents and read it in.
638*0Sstevel@tonic-gate * It's this buffer that's passed to all the other ber decoding
639*0Sstevel@tonic-gate * routines.
640*0Sstevel@tonic-gate */
641*0Sstevel@tonic-gate
642*0Sstevel@tonic-gate #if defined( DOS ) && !defined( _WIN32 )
643*0Sstevel@tonic-gate if ( *len > 65535 ) { /* DOS can't allocate > 64K */
644*0Sstevel@tonic-gate return( LBER_DEFAULT );
645*0Sstevel@tonic-gate }
646*0Sstevel@tonic-gate #endif /* DOS && !_WIN32 */
647*0Sstevel@tonic-gate
648*0Sstevel@tonic-gate if ( ( sb->sb_options & LBER_MAX_INCOMING_SIZE ) &&
649*0Sstevel@tonic-gate *len > sb->sb_max_incoming ) {
650*0Sstevel@tonic-gate return( LBER_DEFAULT );
651*0Sstevel@tonic-gate }
652*0Sstevel@tonic-gate
653*0Sstevel@tonic-gate if ( (ber->ber_buf = (char *) malloc( (size_t)*len )) == NULL ) {
654*0Sstevel@tonic-gate return( LBER_DEFAULT );
655*0Sstevel@tonic-gate }
656*0Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf;
657*0Sstevel@tonic-gate ber->ber_end = ber->ber_buf + *len;
658*0Sstevel@tonic-gate ber->ber_rwptr = ber->ber_buf;
659*0Sstevel@tonic-gate }
660*0Sstevel@tonic-gate
661*0Sstevel@tonic-gate toread = (uintptr_t)ber->ber_end - (uintptr_t)ber->ber_rwptr;
662*0Sstevel@tonic-gate do {
663*0Sstevel@tonic-gate if ( (rc = BerRead( sb, ber->ber_rwptr, (int)toread )) <= 0 ) {
664*0Sstevel@tonic-gate return( LBER_DEFAULT );
665*0Sstevel@tonic-gate }
666*0Sstevel@tonic-gate
667*0Sstevel@tonic-gate toread -= rc;
668*0Sstevel@tonic-gate ber->ber_rwptr += rc;
669*0Sstevel@tonic-gate } while ( toread != 0 ); /* DF SUN for LINT */
670*0Sstevel@tonic-gate
671*0Sstevel@tonic-gate #ifdef LDAP_DEBUG
672*0Sstevel@tonic-gate if ( lber_debug ) {
673*0Sstevel@tonic-gate (void) fprintf( stderr, catgets(slapdcat, 1, 84, "ber_get_next: tag 0x%1$lx len %2$ld contents:\n"),
674*0Sstevel@tonic-gate tag, ber->ber_len );
675*0Sstevel@tonic-gate if ( lber_debug > 1 )
676*0Sstevel@tonic-gate ber_dump( ber, 1 );
677*0Sstevel@tonic-gate }
678*0Sstevel@tonic-gate #endif
679*0Sstevel@tonic-gate
680*0Sstevel@tonic-gate *len = ber->ber_len;
681*0Sstevel@tonic-gate ber->ber_rwptr = NULL;
682*0Sstevel@tonic-gate return( ber->ber_tag );
683*0Sstevel@tonic-gate }
684