xref: /onnv-gate/usr/src/lib/libldap4/ber/io.c (revision 0:68f95e015346)
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