Branch data Line data Source code
1 : : /* crypto/bio/bss_file.c */
2 : : /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 : : * All rights reserved.
4 : : *
5 : : * This package is an SSL implementation written
6 : : * by Eric Young (eay@cryptsoft.com).
7 : : * The implementation was written so as to conform with Netscapes SSL.
8 : : *
9 : : * This library is free for commercial and non-commercial use as long as
10 : : * the following conditions are aheared to. The following conditions
11 : : * apply to all code found in this distribution, be it the RC4, RSA,
12 : : * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 : : * included with this distribution is covered by the same copyright terms
14 : : * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 : : *
16 : : * Copyright remains Eric Young's, and as such any Copyright notices in
17 : : * the code are not to be removed.
18 : : * If this package is used in a product, Eric Young should be given attribution
19 : : * as the author of the parts of the library used.
20 : : * This can be in the form of a textual message at program startup or
21 : : * in documentation (online or textual) provided with the package.
22 : : *
23 : : * Redistribution and use in source and binary forms, with or without
24 : : * modification, are permitted provided that the following conditions
25 : : * are met:
26 : : * 1. Redistributions of source code must retain the copyright
27 : : * notice, this list of conditions and the following disclaimer.
28 : : * 2. Redistributions in binary form must reproduce the above copyright
29 : : * notice, this list of conditions and the following disclaimer in the
30 : : * documentation and/or other materials provided with the distribution.
31 : : * 3. All advertising materials mentioning features or use of this software
32 : : * must display the following acknowledgement:
33 : : * "This product includes cryptographic software written by
34 : : * Eric Young (eay@cryptsoft.com)"
35 : : * The word 'cryptographic' can be left out if the rouines from the library
36 : : * being used are not cryptographic related :-).
37 : : * 4. If you include any Windows specific code (or a derivative thereof) from
38 : : * the apps directory (application code) you must include an acknowledgement:
39 : : * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 : : *
41 : : * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 : : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 : : * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 : : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 : : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 : : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 : : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 : : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 : : * SUCH DAMAGE.
52 : : *
53 : : * The licence and distribution terms for any publically available version or
54 : : * derivative of this code cannot be changed. i.e. this code cannot simply be
55 : : * copied and put under another distribution licence
56 : : * [including the GNU Public Licence.]
57 : : */
58 : :
59 : : /*
60 : : * 03-Dec-1997 rdenny@dc3.com Fix bug preventing use of stdin/stdout
61 : : * with binary data (e.g. asn1parse -inform DER < xxx) under
62 : : * Windows
63 : : */
64 : :
65 : : #ifndef HEADER_BSS_FILE_C
66 : : #define HEADER_BSS_FILE_C
67 : :
68 : : #if defined(__linux) || defined(__sun) || defined(__hpux)
69 : : /* Following definition aliases fopen to fopen64 on above mentioned
70 : : * platforms. This makes it possible to open and sequentially access
71 : : * files larger than 2GB from 32-bit application. It does not allow to
72 : : * traverse them beyond 2GB with fseek/ftell, but on the other hand *no*
73 : : * 32-bit platform permits that, not with fseek/ftell. Not to mention
74 : : * that breaking 2GB limit for seeking would require surgery to *our*
75 : : * API. But sequential access suffices for practical cases when you
76 : : * can run into large files, such as fingerprinting, so we can let API
77 : : * alone. For reference, the list of 32-bit platforms which allow for
78 : : * sequential access of large files without extra "magic" comprise *BSD,
79 : : * Darwin, IRIX...
80 : : */
81 : : #ifndef _FILE_OFFSET_BITS
82 : : #define _FILE_OFFSET_BITS 64
83 : : #endif
84 : : #endif
85 : :
86 : : #include <stdio.h>
87 : : #include <errno.h>
88 : : #include "cryptlib.h"
89 : : #include "bio_lcl.h"
90 : : #include <openssl/err.h>
91 : :
92 : : #if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB)
93 : : #include <nwfileio.h>
94 : : #endif
95 : :
96 : : #if !defined(OPENSSL_NO_STDIO)
97 : :
98 : : static int MS_CALLBACK file_write(BIO *h, const char *buf, int num);
99 : : static int MS_CALLBACK file_read(BIO *h, char *buf, int size);
100 : : static int MS_CALLBACK file_puts(BIO *h, const char *str);
101 : : static int MS_CALLBACK file_gets(BIO *h, char *str, int size);
102 : : static long MS_CALLBACK file_ctrl(BIO *h, int cmd, long arg1, void *arg2);
103 : : static int MS_CALLBACK file_new(BIO *h);
104 : : static int MS_CALLBACK file_free(BIO *data);
105 : : static BIO_METHOD methods_filep=
106 : : {
107 : : BIO_TYPE_FILE,
108 : : "FILE pointer",
109 : : file_write,
110 : : file_read,
111 : : file_puts,
112 : : file_gets,
113 : : file_ctrl,
114 : : file_new,
115 : : file_free,
116 : : NULL,
117 : : };
118 : :
119 : 2289 : BIO *BIO_new_file(const char *filename, const char *mode)
120 : : {
121 : : BIO *ret;
122 : 2289 : FILE *file=NULL;
123 : :
124 : : #if defined(_WIN32) && defined(CP_UTF8)
125 : : int sz, len_0 = (int)strlen(filename)+1;
126 : : DWORD flags;
127 : :
128 : : /*
129 : : * Basically there are three cases to cover: a) filename is
130 : : * pure ASCII string; b) actual UTF-8 encoded string and
131 : : * c) locale-ized string, i.e. one containing 8-bit
132 : : * characters that are meaningful in current system locale.
133 : : * If filename is pure ASCII or real UTF-8 encoded string,
134 : : * MultiByteToWideChar succeeds and _wfopen works. If
135 : : * filename is locale-ized string, chances are that
136 : : * MultiByteToWideChar fails reporting
137 : : * ERROR_NO_UNICODE_TRANSLATION, in which case we fall
138 : : * back to fopen...
139 : : */
140 : : if ((sz=MultiByteToWideChar(CP_UTF8,(flags=MB_ERR_INVALID_CHARS),
141 : : filename,len_0,NULL,0))>0 ||
142 : : (GetLastError()==ERROR_INVALID_FLAGS &&
143 : : (sz=MultiByteToWideChar(CP_UTF8,(flags=0),
144 : : filename,len_0,NULL,0))>0)
145 : : )
146 : : {
147 : : WCHAR wmode[8];
148 : : WCHAR *wfilename = _alloca(sz*sizeof(WCHAR));
149 : :
150 : : if (MultiByteToWideChar(CP_UTF8,flags,
151 : : filename,len_0,wfilename,sz) &&
152 : : MultiByteToWideChar(CP_UTF8,0,mode,strlen(mode)+1,
153 : : wmode,sizeof(wmode)/sizeof(wmode[0])) &&
154 : : (file=_wfopen(wfilename,wmode))==NULL &&
155 : : (errno==ENOENT || errno==EBADF)
156 : : ) /* UTF-8 decode succeeded, but no file, filename
157 : : * could still have been locale-ized... */
158 : : file = fopen(filename,mode);
159 : : }
160 : : else if (GetLastError()==ERROR_NO_UNICODE_TRANSLATION)
161 : : {
162 : : file = fopen(filename,mode);
163 : : }
164 : : #else
165 : 2289 : file=fopen(filename,mode);
166 : : #endif
167 [ + + ]: 2289 : if (file == NULL)
168 : : {
169 : 552 : SYSerr(SYS_F_FOPEN,get_last_sys_error());
170 : 552 : ERR_add_error_data(5,"fopen('",filename,"','",mode,"')");
171 [ + - ]: 552 : if (errno == ENOENT)
172 : 552 : BIOerr(BIO_F_BIO_NEW_FILE,BIO_R_NO_SUCH_FILE);
173 : : else
174 : 0 : BIOerr(BIO_F_BIO_NEW_FILE,ERR_R_SYS_LIB);
175 : : return(NULL);
176 : : }
177 [ - + ]: 1737 : if ((ret=BIO_new(BIO_s_file())) == NULL)
178 : : {
179 : 0 : fclose(file);
180 : 0 : return(NULL);
181 : : }
182 : :
183 : 1737 : BIO_clear_flags(ret,BIO_FLAGS_UPLINK); /* we did fopen -> we disengage UPLINK */
184 : 1737 : BIO_set_fp(ret,file,BIO_CLOSE);
185 : 1737 : return(ret);
186 : : }
187 : :
188 : 2065 : BIO *BIO_new_fp(FILE *stream, int close_flag)
189 : : {
190 : : BIO *ret;
191 : :
192 [ + - ]: 2065 : if ((ret=BIO_new(BIO_s_file())) == NULL)
193 : : return(NULL);
194 : :
195 : 2065 : BIO_set_flags(ret,BIO_FLAGS_UPLINK); /* redundant, left for documentation puposes */
196 : 2065 : BIO_set_fp(ret,stream,close_flag);
197 : 2065 : return(ret);
198 : : }
199 : :
200 : 7910 : BIO_METHOD *BIO_s_file(void)
201 : : {
202 : 7910 : return(&methods_filep);
203 : : }
204 : :
205 : 7910 : static int MS_CALLBACK file_new(BIO *bi)
206 : : {
207 : 7910 : bi->init=0;
208 : 7910 : bi->num=0;
209 : 7910 : bi->ptr=NULL;
210 : 7910 : bi->flags=BIO_FLAGS_UPLINK; /* default to UPLINK */
211 : 7910 : return(1);
212 : : }
213 : :
214 : 15812 : static int MS_CALLBACK file_free(BIO *a)
215 : : {
216 [ + - ]: 15812 : if (a == NULL) return(0);
217 [ + + ]: 15812 : if (a->shutdown)
218 : : {
219 [ + + ][ + - ]: 12281 : if ((a->init) && (a->ptr != NULL))
220 : : {
221 : : if (a->flags&BIO_FLAGS_UPLINK)
222 : : UP_fclose (a->ptr);
223 : : else
224 : 4366 : fclose (a->ptr);
225 : 4366 : a->ptr=NULL;
226 : 4366 : a->flags=BIO_FLAGS_UPLINK;
227 : : }
228 : 12281 : a->init=0;
229 : : }
230 : : return(1);
231 : : }
232 : :
233 : 2775 : static int MS_CALLBACK file_read(BIO *b, char *out, int outl)
234 : : {
235 : 2775 : int ret=0;
236 : :
237 [ + - ][ + - ]: 2775 : if (b->init && (out != NULL))
238 : : {
239 : : if (b->flags&BIO_FLAGS_UPLINK)
240 : : ret=UP_fread(out,1,(int)outl,b->ptr);
241 : : else
242 : 5550 : ret=fread(out,1,(int)outl,(FILE *)b->ptr);
243 [ - + ]: 2775 : if(ret == 0 && (b->flags&BIO_FLAGS_UPLINK)?UP_ferror((FILE *)b->ptr):ferror((FILE *)b->ptr))
244 : : {
245 : 0 : SYSerr(SYS_F_FREAD,get_last_sys_error());
246 : 0 : BIOerr(BIO_F_FILE_READ,ERR_R_SYS_LIB);
247 : 0 : ret=-1;
248 : : }
249 : : }
250 : 2775 : return(ret);
251 : : }
252 : :
253 : 839959 : static int MS_CALLBACK file_write(BIO *b, const char *in, int inl)
254 : : {
255 : 839959 : int ret=0;
256 : :
257 [ + - ][ + - ]: 839959 : if (b->init && (in != NULL))
258 : : {
259 : : if (b->flags&BIO_FLAGS_UPLINK)
260 : : ret=UP_fwrite(in,(int)inl,1,b->ptr);
261 : : else
262 : 839959 : ret=fwrite(in,(int)inl,1,(FILE *)b->ptr);
263 [ + + ]: 839959 : if (ret)
264 : 839954 : ret=inl;
265 : : /* ret=fwrite(in,1,(int)inl,(FILE *)b->ptr); */
266 : : /* according to Tim Hudson <tjh@cryptsoft.com>, the commented
267 : : * out version above can cause 'inl' write calls under
268 : : * some stupid stdio implementations (VMS) */
269 : : }
270 : 839959 : return(ret);
271 : : }
272 : :
273 : 11035 : static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr)
274 : : {
275 : 11035 : long ret=1;
276 : 11035 : FILE *fp=(FILE *)b->ptr;
277 : : FILE **fpp;
278 : : char p[4];
279 : :
280 [ - - - + : 11035 : switch (cmd)
+ - - - +
+ - ]
281 : : {
282 : : case BIO_C_FILE_SEEK:
283 : : case BIO_CTRL_RESET:
284 : : if (b->flags&BIO_FLAGS_UPLINK)
285 : : ret=(long)UP_fseek(b->ptr,num,0);
286 : : else
287 : 0 : ret=(long)fseek(fp,num,0);
288 : 0 : break;
289 : : case BIO_CTRL_EOF:
290 : : if (b->flags&BIO_FLAGS_UPLINK)
291 : : ret=(long)UP_feof(fp);
292 : : else
293 : 0 : ret=(long)feof(fp);
294 : 0 : break;
295 : : case BIO_C_FILE_TELL:
296 : : case BIO_CTRL_INFO:
297 : : if (b->flags&BIO_FLAGS_UPLINK)
298 : : ret=UP_ftell(b->ptr);
299 : : else
300 : 0 : ret=ftell(fp);
301 : 0 : break;
302 : : case BIO_C_SET_FILE_PTR:
303 : 5269 : file_free(b);
304 : 5269 : b->shutdown=(int)num&BIO_CLOSE;
305 : 5269 : b->ptr=ptr;
306 : 5269 : b->init=1;
307 : : #if BIO_FLAGS_UPLINK!=0
308 : : #if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES)
309 : : #define _IOB_ENTRIES 20
310 : : #endif
311 : : #if defined(_IOB_ENTRIES)
312 : : /* Safety net to catch purely internal BIO_set_fp calls */
313 : : if ((size_t)ptr >= (size_t)stdin &&
314 : : (size_t)ptr < (size_t)(stdin+_IOB_ENTRIES))
315 : : BIO_clear_flags(b,BIO_FLAGS_UPLINK);
316 : : #endif
317 : : #endif
318 : : #ifdef UP_fsetmod
319 : : if (b->flags&BIO_FLAGS_UPLINK)
320 : : UP_fsetmod(b->ptr,(char)((num&BIO_FP_TEXT)?'t':'b'));
321 : : else
322 : : #endif
323 : : {
324 : : #if defined(OPENSSL_SYS_WINDOWS)
325 : : int fd = _fileno((FILE*)ptr);
326 : : if (num & BIO_FP_TEXT)
327 : : _setmode(fd,_O_TEXT);
328 : : else
329 : : _setmode(fd,_O_BINARY);
330 : : #elif defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB)
331 : : int fd = fileno((FILE*)ptr);
332 : : /* Under CLib there are differences in file modes */
333 : : if (num & BIO_FP_TEXT)
334 : : setmode(fd,O_TEXT);
335 : : else
336 : : setmode(fd,O_BINARY);
337 : : #elif defined(OPENSSL_SYS_MSDOS)
338 : : int fd = fileno((FILE*)ptr);
339 : : /* Set correct text/binary mode */
340 : : if (num & BIO_FP_TEXT)
341 : : _setmode(fd,_O_TEXT);
342 : : /* Dangerous to set stdin/stdout to raw (unless redirected) */
343 : : else
344 : : {
345 : : if (fd == STDIN_FILENO || fd == STDOUT_FILENO)
346 : : {
347 : : if (isatty(fd) <= 0)
348 : : _setmode(fd,_O_BINARY);
349 : : }
350 : : else
351 : : _setmode(fd,_O_BINARY);
352 : : }
353 : : #elif defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_WIN32_CYGWIN)
354 : : int fd = fileno((FILE*)ptr);
355 : : if (num & BIO_FP_TEXT)
356 : : setmode(fd, O_TEXT);
357 : : else
358 : : setmode(fd, O_BINARY);
359 : : #endif
360 : : }
361 : 5269 : break;
362 : : case BIO_C_SET_FILENAME:
363 : 2634 : file_free(b);
364 : 2634 : b->shutdown=(int)num&BIO_CLOSE;
365 [ - + ]: 2634 : if (num & BIO_FP_APPEND)
366 : : {
367 [ # # ]: 0 : if (num & BIO_FP_READ)
368 : 0 : BUF_strlcpy(p,"a+",sizeof p);
369 : 0 : else BUF_strlcpy(p,"a",sizeof p);
370 : : }
371 [ - + ]: 2634 : else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE))
372 : 0 : BUF_strlcpy(p,"r+",sizeof p);
373 [ + + ]: 2634 : else if (num & BIO_FP_WRITE)
374 : 42 : BUF_strlcpy(p,"w",sizeof p);
375 [ + - ]: 2592 : else if (num & BIO_FP_READ)
376 : 2592 : BUF_strlcpy(p,"r",sizeof p);
377 : : else
378 : : {
379 : 0 : BIOerr(BIO_F_FILE_CTRL,BIO_R_BAD_FOPEN_MODE);
380 : 0 : ret=0;
381 : 0 : break;
382 : : }
383 : : #if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_WIN32_CYGWIN)
384 : : if (!(num & BIO_FP_TEXT))
385 : : strcat(p,"b");
386 : : else
387 : : strcat(p,"t");
388 : : #endif
389 : : #if defined(OPENSSL_SYS_NETWARE)
390 : : if (!(num & BIO_FP_TEXT))
391 : : strcat(p,"b");
392 : : else
393 : : strcat(p,"t");
394 : : #endif
395 : 2634 : fp=fopen(ptr,p);
396 [ + + ]: 2634 : if (fp == NULL)
397 : : {
398 : 5 : SYSerr(SYS_F_FOPEN,get_last_sys_error());
399 : 5 : ERR_add_error_data(5,"fopen('",ptr,"','",p,"')");
400 : 5 : BIOerr(BIO_F_FILE_CTRL,ERR_R_SYS_LIB);
401 : 5 : ret=0;
402 : 5 : break;
403 : : }
404 : 2629 : b->ptr=fp;
405 : 2629 : b->init=1;
406 : 2629 : BIO_clear_flags(b,BIO_FLAGS_UPLINK); /* we did fopen -> we disengage UPLINK */
407 : 2629 : break;
408 : : case BIO_C_GET_FILE_PTR:
409 : : /* the ptr parameter is actually a FILE ** in this case. */
410 [ # # ]: 0 : if (ptr != NULL)
411 : : {
412 : 0 : fpp=(FILE **)ptr;
413 : 0 : *fpp=(FILE *)b->ptr;
414 : : }
415 : : break;
416 : : case BIO_CTRL_GET_CLOSE:
417 : 0 : ret=(long)b->shutdown;
418 : 0 : break;
419 : : case BIO_CTRL_SET_CLOSE:
420 : 0 : b->shutdown=(int)num;
421 : 0 : break;
422 : : case BIO_CTRL_FLUSH:
423 : : if (b->flags&BIO_FLAGS_UPLINK)
424 : : UP_fflush(b->ptr);
425 : : else
426 : 2296 : fflush((FILE *)b->ptr);
427 : 2296 : break;
428 : : case BIO_CTRL_DUP:
429 : : ret=1;
430 : : break;
431 : :
432 : : case BIO_CTRL_WPENDING:
433 : : case BIO_CTRL_PENDING:
434 : : case BIO_CTRL_PUSH:
435 : : case BIO_CTRL_POP:
436 : : default:
437 : 836 : ret=0;
438 : 836 : break;
439 : : }
440 : 11035 : return(ret);
441 : : }
442 : :
443 : 332145 : static int MS_CALLBACK file_gets(BIO *bp, char *buf, int size)
444 : : {
445 : 332145 : int ret=0;
446 : :
447 : 332145 : buf[0]='\0';
448 : : if (bp->flags&BIO_FLAGS_UPLINK)
449 : : {
450 : : if (!UP_fgets(buf,size,bp->ptr))
451 : : goto err;
452 : : }
453 : : else
454 : : {
455 [ + + ]: 332145 : if (!fgets(buf,size,(FILE *)bp->ptr))
456 : : goto err;
457 : : }
458 [ + - ]: 330607 : if (buf[0] != '\0')
459 : 330607 : ret=strlen(buf);
460 : : err:
461 : 332145 : return(ret);
462 : : }
463 : :
464 : 20053 : static int MS_CALLBACK file_puts(BIO *bp, const char *str)
465 : : {
466 : : int n,ret;
467 : :
468 : 20053 : n=strlen(str);
469 : 20053 : ret=file_write(bp,str,n);
470 : 20053 : return(ret);
471 : : }
472 : :
473 : : #endif /* OPENSSL_NO_STDIO */
474 : :
475 : : #endif /* HEADER_BSS_FILE_C */
476 : :
477 : :
|