ssl/libcrypto/src/crypto/bio/bss_file.c
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     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  © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
    66  */
       
    67  
       
    68 
       
    69 #ifndef HEADER_BSS_FILE_C
       
    70 #define HEADER_BSS_FILE_C
       
    71 
       
    72 #if defined(__linux) || defined(__sun) || defined(__hpux)
       
    73 /* Following definition aliases fopen to fopen64 on above mentioned
       
    74  * platforms. This makes it possible to open and sequentially access
       
    75  * files larger than 2GB from 32-bit application. It does not allow to
       
    76  * traverse them beyond 2GB with fseek/ftell, but on the other hand *no*
       
    77  * 32-bit platform permits that, not with fseek/ftell. Not to mention
       
    78  * that breaking 2GB limit for seeking would require surgery to *our*
       
    79  * API. But sequential access suffices for practical cases when you
       
    80  * can run into large files, such as fingerprinting, so we can let API
       
    81  * alone. For reference, the list of 32-bit platforms which allow for
       
    82  * sequential access of large files without extra "magic" comprise *BSD,
       
    83  * Darwin, IRIX...
       
    84  */
       
    85 #ifndef _FILE_OFFSET_BITS
       
    86 #define _FILE_OFFSET_BITS 64
       
    87 #endif
       
    88 #endif
       
    89 
       
    90 #include <stdio.h>
       
    91 #include <errno.h>
       
    92 #include "cryptlib.h"
       
    93 #include "bio_lcl.h"
       
    94 #include <openssl/err.h>
       
    95 #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
       
    96 #include "libcrypto_wsd_macros.h"
       
    97 #include "libcrypto_wsd.h"
       
    98 #endif
       
    99 
       
   100 
       
   101 #if !defined(OPENSSL_NO_STDIO)
       
   102 
       
   103 static int MS_CALLBACK file_write(BIO *h, const char *buf, int num);
       
   104 static int MS_CALLBACK file_read(BIO *h, char *buf, int size);
       
   105 static int MS_CALLBACK file_puts(BIO *h, const char *str);
       
   106 static int MS_CALLBACK file_gets(BIO *h, char *str, int size);
       
   107 static long MS_CALLBACK file_ctrl(BIO *h, int cmd, long arg1, void *arg2);
       
   108 static int MS_CALLBACK file_new(BIO *h);
       
   109 static int MS_CALLBACK file_free(BIO *data);
       
   110 #ifndef EMULATOR
       
   111 static BIO_METHOD methods_filep=
       
   112 	{
       
   113 	BIO_TYPE_FILE,
       
   114 	"FILE pointer",
       
   115 	file_write,
       
   116 	file_read,
       
   117 	file_puts,
       
   118 	file_gets,
       
   119 	file_ctrl,
       
   120 	file_new,
       
   121 	file_free,
       
   122 	NULL,
       
   123 	};
       
   124 #else
       
   125 GET_STATIC_VAR_FROM_TLS(methods_filep,bss_file,BIO_METHOD)
       
   126 #define methods_filep (*GET_WSD_VAR_NAME(methods_filep,bss_file,s)())
       
   127 const BIO_METHOD temp_s_methods_filep=
       
   128 	{
       
   129 	BIO_TYPE_FILE,
       
   130 	"FILE pointer",
       
   131 	file_write,
       
   132 	file_read,
       
   133 	file_puts,
       
   134 	file_gets,
       
   135 	file_ctrl,
       
   136 	file_new,
       
   137 	file_free,
       
   138 	NULL,
       
   139 	};
       
   140 
       
   141 #endif	
       
   142 	
       
   143 
       
   144 EXPORT_C BIO *BIO_new_file(const char *filename, const char *mode)
       
   145 	{
       
   146 	BIO *ret;
       
   147 	FILE *file;
       
   148 
       
   149 	if ((file=fopen(filename,mode)) == NULL)
       
   150 		{
       
   151 		SYSerr(SYS_F_FOPEN,get_last_sys_error());
       
   152 		ERR_add_error_data(5,"fopen('",filename,"','",mode,"')");
       
   153 		if (errno == ENOENT)
       
   154 			BIOerr(BIO_F_BIO_NEW_FILE,BIO_R_NO_SUCH_FILE);
       
   155 		else
       
   156 			BIOerr(BIO_F_BIO_NEW_FILE,ERR_R_SYS_LIB);
       
   157 		return(NULL);
       
   158 		}
       
   159 	if ((ret=BIO_new(BIO_s_file_internal())) == NULL)
       
   160 	{
       
   161 		fclose(file);
       
   162   	return(NULL);
       
   163 	}	
       
   164 
       
   165 	BIO_clear_flags(ret,BIO_FLAGS_UPLINK); /* we did fopen -> we disengage UPLINK */
       
   166 	BIO_set_fp(ret,file,BIO_CLOSE);
       
   167 	return(ret);
       
   168 	}
       
   169 
       
   170 EXPORT_C BIO *BIO_new_fp(FILE *stream, int close_flag)
       
   171 	{
       
   172 	BIO *ret;
       
   173 
       
   174 	if ((ret=BIO_new(BIO_s_file())) == NULL)
       
   175 		return(NULL);
       
   176 
       
   177 	BIO_set_flags(ret,BIO_FLAGS_UPLINK); /* redundant, left for documentation puposes */
       
   178 	BIO_set_fp(ret,stream,close_flag);
       
   179 	return(ret);
       
   180 	}
       
   181 
       
   182 EXPORT_C BIO_METHOD *BIO_s_file(void)
       
   183 	{
       
   184 	return(&methods_filep);
       
   185 	}
       
   186 
       
   187 static int MS_CALLBACK file_new(BIO *bi)
       
   188 	{
       
   189 	bi->init=0;
       
   190 	bi->num=0;
       
   191 	bi->ptr=NULL;
       
   192 	bi->flags=BIO_FLAGS_UPLINK; /* default to UPLINK */
       
   193 	return(1);
       
   194 	}
       
   195 
       
   196 static int MS_CALLBACK file_free(BIO *a)
       
   197 	{
       
   198 	if (a == NULL) return(0);
       
   199 	if (a->shutdown)
       
   200 		{
       
   201 		if ((a->init) && (a->ptr != NULL))
       
   202 			{
       
   203 			if (a->flags&BIO_FLAGS_UPLINK)
       
   204 				UP_fclose (a->ptr);
       
   205 			else
       
   206 				fclose (a->ptr);
       
   207 			a->ptr=NULL;
       
   208 			a->flags=BIO_FLAGS_UPLINK;
       
   209 			}
       
   210 		a->init=0;
       
   211 		}
       
   212 	return(1);
       
   213 	}
       
   214 	
       
   215 static int MS_CALLBACK file_read(BIO *b, char *out, int outl)
       
   216 	{
       
   217 	int ret=0;
       
   218 
       
   219 	if (b->init && (out != NULL))
       
   220 		{
       
   221 		if (b->flags&BIO_FLAGS_UPLINK)
       
   222 			ret=UP_fread(out,1,(int)outl,b->ptr);
       
   223 		else
       
   224 			ret=fread(out,1,(int)outl,(FILE *)b->ptr);
       
   225 		if(ret == 0 && (b->flags&BIO_FLAGS_UPLINK)?UP_ferror((FILE *)b->ptr):ferror((FILE *)b->ptr))
       
   226 			{
       
   227 			SYSerr(SYS_F_FREAD,get_last_sys_error());
       
   228 			BIOerr(BIO_F_FILE_READ,ERR_R_SYS_LIB);
       
   229 			ret=-1;
       
   230 			}
       
   231 		}
       
   232 	return(ret);
       
   233 	}
       
   234 
       
   235 static int MS_CALLBACK file_write(BIO *b, const char *in, int inl)
       
   236 	{
       
   237 	int ret=0;
       
   238 
       
   239 	if (b->init && (in != NULL))
       
   240 		{
       
   241 		if (b->flags&BIO_FLAGS_UPLINK)
       
   242 			ret=UP_fwrite(in,(int)inl,1,b->ptr);
       
   243 		else
       
   244 			ret=fwrite(in,(int)inl,1,(FILE *)b->ptr);
       
   245 		if (ret)
       
   246 			ret=inl;
       
   247 		/* ret=fwrite(in,1,(int)inl,(FILE *)b->ptr); */
       
   248 		/* according to Tim Hudson <tjh@cryptsoft.com>, the commented
       
   249 		 * out version above can cause 'inl' write calls under
       
   250 		 * some stupid stdio implementations (VMS) */
       
   251 		}
       
   252 	return(ret);
       
   253 	}
       
   254 
       
   255 static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr)
       
   256 	{
       
   257 	long ret=1;
       
   258 	FILE *fp=(FILE *)b->ptr;
       
   259 	FILE **fpp;
       
   260 	char p[4];
       
   261 
       
   262 	switch (cmd)
       
   263 		{
       
   264 	case BIO_C_FILE_SEEK:
       
   265 	case BIO_CTRL_RESET:
       
   266 		if (b->flags&BIO_FLAGS_UPLINK)
       
   267 			ret=(long)UP_fseek(b->ptr,num,0);
       
   268 		else
       
   269 			ret=(long)fseek(fp,num,0);
       
   270 		break;
       
   271 	case BIO_CTRL_EOF:
       
   272 		if (b->flags&BIO_FLAGS_UPLINK)
       
   273 			ret=(long)UP_feof(fp);
       
   274 		else
       
   275 			ret=(long)feof(fp);
       
   276 		break;
       
   277 	case BIO_C_FILE_TELL:
       
   278 	case BIO_CTRL_INFO:
       
   279 		if (b->flags&BIO_FLAGS_UPLINK)
       
   280 			ret=UP_ftell(b->ptr);
       
   281 		else
       
   282 			ret=ftell(fp);
       
   283 		break;
       
   284 	case BIO_C_SET_FILE_PTR:
       
   285 		file_free(b);
       
   286 		b->shutdown=(int)num&BIO_CLOSE;
       
   287 		b->ptr=ptr;
       
   288 		b->init=1;
       
   289 #if BIO_FLAGS_UPLINK!=0
       
   290 #if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES)
       
   291 #define _IOB_ENTRIES 20
       
   292 #endif
       
   293 #if defined(_IOB_ENTRIES)
       
   294 		/* Safety net to catch purely internal BIO_set_fp calls */
       
   295 		if ((size_t)ptr >= (size_t)stdin &&
       
   296 		    (size_t)ptr <  (size_t)(stdin+_IOB_ENTRIES))
       
   297 			BIO_clear_flags(b,BIO_FLAGS_UPLINK);
       
   298 #endif
       
   299 #endif
       
   300 #ifdef UP_fsetmode
       
   301 		if (b->flags&BIO_FLAGS_UPLINK)
       
   302 			UP_fsetmode(b->ptr,num&BIO_FP_TEXT?'t':'b');
       
   303 		else
       
   304 #endif
       
   305 		{
       
   306 #if defined(OPENSSL_SYS_WINDOWS)
       
   307 		int fd = fileno((FILE*)ptr);
       
   308 		if (num & BIO_FP_TEXT)
       
   309 			_setmode(fd,_O_TEXT);
       
   310 		else
       
   311 			_setmode(fd,_O_BINARY);
       
   312 #elif defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB)
       
   313 		int fd = fileno((FILE*)ptr);
       
   314          /* Under CLib there are differences in file modes
       
   315          */
       
   316 		if (num & BIO_FP_TEXT)
       
   317 			_setmode(fd,O_TEXT);
       
   318 		else
       
   319 			_setmode(fd,O_BINARY);
       
   320 #elif defined(OPENSSL_SYS_MSDOS)
       
   321 		int fd = fileno((FILE*)ptr);
       
   322 		/* Set correct text/binary mode */
       
   323 		if (num & BIO_FP_TEXT)
       
   324 			_setmode(fd,_O_TEXT);
       
   325 		/* Dangerous to set stdin/stdout to raw (unless redirected) */
       
   326 		else
       
   327 			{
       
   328 			if (fd == STDIN_FILENO || fd == STDOUT_FILENO)
       
   329 				{
       
   330 				if (isatty(fd) <= 0)
       
   331 					_setmode(fd,_O_BINARY);
       
   332 				}
       
   333 			else
       
   334 				_setmode(fd,_O_BINARY);
       
   335 			}
       
   336 #elif defined(OPENSSL_SYS_OS2)
       
   337 		int fd = fileno((FILE*)ptr);
       
   338 		if (num & BIO_FP_TEXT)
       
   339 			setmode(fd, O_TEXT);
       
   340 		else
       
   341 			setmode(fd, O_BINARY);
       
   342 #endif
       
   343 		}
       
   344 		break;
       
   345 	case BIO_C_SET_FILENAME:
       
   346 		file_free(b);
       
   347 		b->shutdown=(int)num&BIO_CLOSE;
       
   348 		if (num & BIO_FP_APPEND)
       
   349 			{
       
   350 			if (num & BIO_FP_READ)
       
   351 				BUF_strlcpy(p,"a+",sizeof p);
       
   352 			else	BUF_strlcpy(p,"a",sizeof p);
       
   353 			}
       
   354 		else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE))
       
   355 			BUF_strlcpy(p,"r+",sizeof p);
       
   356 		else if (num & BIO_FP_WRITE)
       
   357 			BUF_strlcpy(p,"w",sizeof p);
       
   358 		else if (num & BIO_FP_READ)
       
   359 			BUF_strlcpy(p,"r",sizeof p);
       
   360 		else
       
   361 			{
       
   362 			BIOerr(BIO_F_FILE_CTRL,BIO_R_BAD_FOPEN_MODE);
       
   363 			ret=0;
       
   364 			break;
       
   365 			}
       
   366 #if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_WIN32_CYGWIN)
       
   367 		if (!(num & BIO_FP_TEXT))
       
   368 			strcat(p,"b");
       
   369 		else
       
   370 			strcat(p,"t");
       
   371 #endif
       
   372 #if defined(OPENSSL_SYS_NETWARE)
       
   373 		if (!(num & BIO_FP_TEXT))
       
   374 			strcat(p,"b");
       
   375 		else
       
   376 			strcat(p,"t");
       
   377 #endif
       
   378 		fp=fopen(ptr,p);
       
   379 		if (fp == NULL)
       
   380 			{
       
   381 			SYSerr(SYS_F_FOPEN,get_last_sys_error());
       
   382 			ERR_add_error_data(5,"fopen('",ptr,"','",p,"')");
       
   383 			BIOerr(BIO_F_FILE_CTRL,ERR_R_SYS_LIB);
       
   384 			ret=0;
       
   385 			break;
       
   386 			}
       
   387 		b->ptr=fp;
       
   388 		b->init=1;
       
   389 		BIO_clear_flags(b,BIO_FLAGS_UPLINK); /* we did fopen -> we disengage UPLINK */
       
   390 		break;
       
   391 	case BIO_C_GET_FILE_PTR:
       
   392 		/* the ptr parameter is actually a FILE ** in this case. */
       
   393 		if (ptr != NULL)
       
   394 			{
       
   395 			fpp=(FILE **)ptr;
       
   396 			*fpp=(FILE *)b->ptr;
       
   397 			}
       
   398 		break;
       
   399 	case BIO_CTRL_GET_CLOSE:
       
   400 		ret=(long)b->shutdown;
       
   401 		break;
       
   402 	case BIO_CTRL_SET_CLOSE:
       
   403 		b->shutdown=(int)num;
       
   404 		break;
       
   405 	case BIO_CTRL_FLUSH:
       
   406 		if (b->flags&BIO_FLAGS_UPLINK)
       
   407 			UP_fflush(b->ptr);
       
   408 		else
       
   409 			fflush((FILE *)b->ptr);
       
   410 		break;
       
   411 	case BIO_CTRL_DUP:
       
   412 		ret=1;
       
   413 		break;
       
   414 
       
   415 	case BIO_CTRL_WPENDING:
       
   416 	case BIO_CTRL_PENDING:
       
   417 	case BIO_CTRL_PUSH:
       
   418 	case BIO_CTRL_POP:
       
   419 	default:
       
   420 		ret=0;
       
   421 		break;
       
   422 		}
       
   423 	return(ret);
       
   424 	}
       
   425 
       
   426 static int MS_CALLBACK file_gets(BIO *bp, char *buf, int size)
       
   427 	{
       
   428 	int ret=0;
       
   429 
       
   430 	buf[0]='\0';
       
   431 	if (bp->flags&BIO_FLAGS_UPLINK)
       
   432 		UP_fgets(buf,size,bp->ptr);
       
   433 	else
       
   434 		fgets(buf,size,(FILE *)bp->ptr);
       
   435 	if (buf[0] != '\0')
       
   436 		ret=strlen(buf);
       
   437 	return(ret);
       
   438 	}
       
   439 
       
   440 static int MS_CALLBACK file_puts(BIO *bp, const char *str)
       
   441 	{
       
   442 	int n,ret;
       
   443 
       
   444 	n=strlen(str);
       
   445 	ret=file_write(bp,str,n);
       
   446 	return(ret);
       
   447 	}
       
   448 
       
   449 #endif /* OPENSSL_NO_STDIO */
       
   450 
       
   451 #endif /* HEADER_BSS_FILE_C */
       
   452 
       
   453