1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <openssl/objects.h>
5 #include <openssl/comp.h>
6 #include <openssl/err.h>
7 
8 COMP_METHOD *COMP_zlib(void );
9 
10 static COMP_METHOD zlib_method_nozlib={
11 	NID_undef,
12 	"(undef)",
13 	NULL,
14 	NULL,
15 	NULL,
16 	NULL,
17 	NULL,
18 	NULL,
19 	};
20 
21 #ifndef ZLIB
22 #undef ZLIB_SHARED
23 #else
24 
25 #include <zlib.h>
26 
27 static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
28 	unsigned int olen, unsigned char *in, unsigned int ilen);
29 static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
30 	unsigned int olen, unsigned char *in, unsigned int ilen);
31 
32 static int zz_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,
33 	uLong sourceLen);
34 
35 static COMP_METHOD zlib_method={
36 	NID_zlib_compression,
37 	LN_zlib_compression,
38 	NULL,
39 	NULL,
40 	zlib_compress_block,
41 	zlib_expand_block,
42 	NULL,
43 	NULL,
44 	};
45 
46 /*
47  * When OpenSSL is built on Windows, we do not want to require that
48  * the ZLIB.DLL be available in order for the OpenSSL DLLs to
49  * work.  Therefore, all ZLIB routines are loaded at run time
50  * and we do not link to a .LIB file.
51  */
52 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
53 # include <windows.h>
54 #endif /* !(OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32) */
55 
56 #ifdef ZLIB_SHARED
57 #include <openssl/dso.h>
58 
59 /* Function pointers */
60 typedef int (*compress_ft)(Bytef *dest,uLongf *destLen,
61 	const Bytef *source, uLong sourceLen);
62 typedef int (*inflateEnd_ft)(z_streamp strm);
63 typedef int (*inflate_ft)(z_streamp strm, int flush);
64 typedef int (*inflateInit__ft)(z_streamp strm,
65 	const char * version, int stream_size);
66 static compress_ft	p_compress=NULL;
67 static inflateEnd_ft	p_inflateEnd=NULL;
68 static inflate_ft	p_inflate=NULL;
69 static inflateInit__ft	p_inflateInit_=NULL;
70 
71 static int zlib_loaded = 0;     /* only attempt to init func pts once */
72 static DSO *zlib_dso = NULL;
73 
74 #define compress                p_compress
75 #define inflateEnd              p_inflateEnd
76 #define inflate                 p_inflate
77 #define inflateInit_            p_inflateInit_
78 #endif /* ZLIB_SHARED */
79 
zlib_compress_block(COMP_CTX * ctx,unsigned char * out,unsigned int olen,unsigned char * in,unsigned int ilen)80 static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
81 	     unsigned int olen, unsigned char *in, unsigned int ilen)
82 	{
83 	unsigned long l;
84 	int i;
85 	int clear=1;
86 
87 	if (ilen > 128)
88 		{
89 		out[0]=1;
90 		l=olen-1;
91 		i=compress(&(out[1]),&l,in,(unsigned long)ilen);
92 		if (i != Z_OK)
93 			return(-1);
94 		if (ilen > l)
95 			{
96 			clear=0;
97 			l++;
98 			}
99 		}
100 	if (clear)
101 		{
102 		out[0]=0;
103 		memcpy(&(out[1]),in,ilen);
104 		l=ilen+1;
105 		}
106 #ifdef DEBUG_ZLIB
107 	fprintf(stderr,"compress(%4d)->%4d %s\n",
108 		ilen,(int)l,(clear)?"clear":"zlib");
109 #endif
110 	return((int)l);
111 	}
112 
zlib_expand_block(COMP_CTX * ctx,unsigned char * out,unsigned int olen,unsigned char * in,unsigned int ilen)113 static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
114 	     unsigned int olen, unsigned char *in, unsigned int ilen)
115 	{
116 	unsigned long l;
117 	int i;
118 
119 	if (in[0])
120 		{
121 		l=olen;
122 		i=zz_uncompress(out,&l,&(in[1]),(unsigned long)ilen-1);
123 		if (i != Z_OK)
124 			return(-1);
125 		}
126 	else
127 		{
128 		memcpy(out,&(in[1]),ilen-1);
129 		l=ilen-1;
130 		}
131 #ifdef DEBUG_ZLIB
132         fprintf(stderr,"expand  (%4d)->%4d %s\n",
133 		ilen,(int)l,in[0]?"zlib":"clear");
134 #endif
135 	return((int)l);
136 	}
137 
zz_uncompress(Bytef * dest,uLongf * destLen,const Bytef * source,uLong sourceLen)138 static int zz_uncompress (Bytef *dest, uLongf *destLen, const Bytef *source,
139 	     uLong sourceLen)
140 {
141     z_stream stream;
142     int err;
143 
144     stream.next_in = (Bytef*)source;
145     stream.avail_in = (uInt)sourceLen;
146     /* Check for source > 64K on 16-bit machine: */
147     if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
148 
149     stream.next_out = dest;
150     stream.avail_out = (uInt)*destLen;
151     if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
152 
153     stream.zalloc = (alloc_func)0;
154     stream.zfree = (free_func)0;
155 
156     err = inflateInit(&stream);
157     if (err != Z_OK) return err;
158 
159     err = inflate(&stream, Z_FINISH);
160     if (err != Z_STREAM_END) {
161         inflateEnd(&stream);
162         return err;
163     }
164     *destLen = stream.total_out;
165 
166     err = inflateEnd(&stream);
167     return err;
168 }
169 
170 #endif
171 
COMP_zlib(void)172 COMP_METHOD *COMP_zlib(void)
173 	{
174 	COMP_METHOD *meth = &zlib_method_nozlib;
175 
176 #ifdef ZLIB_SHARED
177 	if (!zlib_loaded)
178 		{
179 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
180 		zlib_dso = DSO_load(NULL, "ZLIB1", NULL, 0);
181 #else
182 		zlib_dso = DSO_load(NULL, "z", NULL, 0);
183 #endif
184 		if (zlib_dso != NULL)
185 			{
186 			p_compress
187 				= (compress_ft) DSO_bind_func(zlib_dso,
188 					"compress");
189 			p_inflateEnd
190 				= (inflateEnd_ft) DSO_bind_func(zlib_dso,
191 					"inflateEnd");
192 			p_inflate
193 				= (inflate_ft) DSO_bind_func(zlib_dso,
194 					"inflate");
195 			p_inflateInit_
196 				= (inflateInit__ft) DSO_bind_func(zlib_dso,
197 					"inflateInit_");
198 
199 			if (p_compress && p_inflateEnd && p_inflate
200 				&& p_inflateInit_)
201 				zlib_loaded++;
202 			}
203 		}
204 
205 #endif
206 #ifdef ZLIB_SHARED
207 	if (zlib_loaded)
208 #endif
209 #if defined(ZLIB) || defined(ZLIB_SHARED)
210 		meth = &zlib_method;
211 #endif
212 
213 	return(meth);
214 	}
215 
216