1 /* 2 * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #ifndef HEADER_BSS_FILE_C 11 # define HEADER_BSS_FILE_C 12 13 # if defined(__linux) || defined(__sun) || defined(__hpux) 14 /* 15 * Following definition aliases fopen to fopen64 on above mentioned 16 * platforms. This makes it possible to open and sequentially access files 17 * larger than 2GB from 32-bit application. It does not allow to traverse 18 * them beyond 2GB with fseek/ftell, but on the other hand *no* 32-bit 19 * platform permits that, not with fseek/ftell. Not to mention that breaking 20 * 2GB limit for seeking would require surgery to *our* API. But sequential 21 * access suffices for practical cases when you can run into large files, 22 * such as fingerprinting, so we can let API alone. For reference, the list 23 * of 32-bit platforms which allow for sequential access of large files 24 * without extra "magic" comprise *BSD, Darwin, IRIX... 25 */ 26 # ifndef _FILE_OFFSET_BITS 27 # define _FILE_OFFSET_BITS 64 28 # endif 29 # endif 30 31 # include <stdio.h> 32 # include <errno.h> 33 # include "bio_lcl.h" 34 # include <openssl/err.h> 35 36 # if !defined(OPENSSL_NO_STDIO) 37 38 static int file_write(BIO *h, const char *buf, int num); 39 static int file_read(BIO *h, char *buf, int size); 40 static int file_puts(BIO *h, const char *str); 41 static int file_gets(BIO *h, char *str, int size); 42 static long file_ctrl(BIO *h, int cmd, long arg1, void *arg2); 43 static int file_new(BIO *h); 44 static int file_free(BIO *data); 45 static const BIO_METHOD methods_filep = { 46 BIO_TYPE_FILE, 47 "FILE pointer", 48 /* TODO: Convert to new style write function */ 49 bwrite_conv, 50 file_write, 51 /* TODO: Convert to new style read function */ 52 bread_conv, 53 file_read, 54 file_puts, 55 file_gets, 56 file_ctrl, 57 file_new, 58 file_free, 59 NULL, /* file_callback_ctrl */ 60 }; 61 62 BIO *BIO_new_file(const char *filename, const char *mode) 63 { 64 BIO *ret; 65 FILE *file = openssl_fopen(filename, mode); 66 int fp_flags = BIO_CLOSE; 67 68 if (strchr(mode, 'b') == NULL) 69 fp_flags |= BIO_FP_TEXT; 70 71 if (file == NULL) { 72 SYSerr(SYS_F_FOPEN, get_last_sys_error()); 73 ERR_add_error_data(5, "fopen('", filename, "','", mode, "')"); 74 if (errno == ENOENT 75 # ifdef ENXIO 76 || errno == ENXIO 77 # endif 78 ) 79 BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE); 80 else 81 BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB); 82 return NULL; 83 } 84 if ((ret = BIO_new(BIO_s_file())) == NULL) { 85 fclose(file); 86 return NULL; 87 } 88 89 BIO_clear_flags(ret, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage 90 * UPLINK */ 91 BIO_set_fp(ret, file, fp_flags); 92 return ret; 93 } 94 95 BIO *BIO_new_fp(FILE *stream, int close_flag) 96 { 97 BIO *ret; 98 99 if ((ret = BIO_new(BIO_s_file())) == NULL) 100 return NULL; 101 102 /* redundant flag, left for documentation purposes */ 103 BIO_set_flags(ret, BIO_FLAGS_UPLINK); 104 BIO_set_fp(ret, stream, close_flag); 105 return ret; 106 } 107 108 const BIO_METHOD *BIO_s_file(void) 109 { 110 return &methods_filep; 111 } 112 113 static int file_new(BIO *bi) 114 { 115 bi->init = 0; 116 bi->num = 0; 117 bi->ptr = NULL; 118 bi->flags = BIO_FLAGS_UPLINK; /* default to UPLINK */ 119 return 1; 120 } 121 122 static int file_free(BIO *a) 123 { 124 if (a == NULL) 125 return 0; 126 if (a->shutdown) { 127 if ((a->init) && (a->ptr != NULL)) { 128 if (a->flags & BIO_FLAGS_UPLINK) 129 UP_fclose(a->ptr); 130 else 131 fclose(a->ptr); 132 a->ptr = NULL; 133 a->flags = BIO_FLAGS_UPLINK; 134 } 135 a->init = 0; 136 } 137 return 1; 138 } 139 140 static int file_read(BIO *b, char *out, int outl) 141 { 142 int ret = 0; 143 144 if (b->init && (out != NULL)) { 145 if (b->flags & BIO_FLAGS_UPLINK) 146 ret = UP_fread(out, 1, (int)outl, b->ptr); 147 else 148 ret = fread(out, 1, (int)outl, (FILE *)b->ptr); 149 if (ret == 0 150 && (b->flags & BIO_FLAGS_UPLINK) ? UP_ferror((FILE *)b->ptr) : 151 ferror((FILE *)b->ptr)) { 152 SYSerr(SYS_F_FREAD, get_last_sys_error()); 153 BIOerr(BIO_F_FILE_READ, ERR_R_SYS_LIB); 154 ret = -1; 155 } 156 } 157 return ret; 158 } 159 160 static int file_write(BIO *b, const char *in, int inl) 161 { 162 int ret = 0; 163 164 if (b->init && (in != NULL)) { 165 if (b->flags & BIO_FLAGS_UPLINK) 166 ret = UP_fwrite(in, (int)inl, 1, b->ptr); 167 else 168 ret = fwrite(in, (int)inl, 1, (FILE *)b->ptr); 169 if (ret) 170 ret = inl; 171 /* ret=fwrite(in,1,(int)inl,(FILE *)b->ptr); */ 172 /* 173 * according to Tim Hudson <tjh@openssl.org>, the commented out 174 * version above can cause 'inl' write calls under some stupid stdio 175 * implementations (VMS) 176 */ 177 } 178 return ret; 179 } 180 181 static long file_ctrl(BIO *b, int cmd, long num, void *ptr) 182 { 183 long ret = 1; 184 FILE *fp = (FILE *)b->ptr; 185 FILE **fpp; 186 char p[4]; 187 int st; 188 189 switch (cmd) { 190 case BIO_C_FILE_SEEK: 191 case BIO_CTRL_RESET: 192 if (b->flags & BIO_FLAGS_UPLINK) 193 ret = (long)UP_fseek(b->ptr, num, 0); 194 else 195 ret = (long)fseek(fp, num, 0); 196 break; 197 case BIO_CTRL_EOF: 198 if (b->flags & BIO_FLAGS_UPLINK) 199 ret = (long)UP_feof(fp); 200 else 201 ret = (long)feof(fp); 202 break; 203 case BIO_C_FILE_TELL: 204 case BIO_CTRL_INFO: 205 if (b->flags & BIO_FLAGS_UPLINK) 206 ret = UP_ftell(b->ptr); 207 else 208 ret = ftell(fp); 209 break; 210 case BIO_C_SET_FILE_PTR: 211 file_free(b); 212 b->shutdown = (int)num & BIO_CLOSE; 213 b->ptr = ptr; 214 b->init = 1; 215 # if BIO_FLAGS_UPLINK!=0 216 # if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES) 217 # define _IOB_ENTRIES 20 218 # endif 219 /* Safety net to catch purely internal BIO_set_fp calls */ 220 # if defined(_MSC_VER) && _MSC_VER>=1900 221 if (ptr == stdin || ptr == stdout || ptr == stderr) 222 BIO_clear_flags(b, BIO_FLAGS_UPLINK); 223 # elif defined(_IOB_ENTRIES) 224 if ((size_t)ptr >= (size_t)stdin && 225 (size_t)ptr < (size_t)(stdin + _IOB_ENTRIES)) 226 BIO_clear_flags(b, BIO_FLAGS_UPLINK); 227 # endif 228 # endif 229 # ifdef UP_fsetmod 230 if (b->flags & BIO_FLAGS_UPLINK) 231 UP_fsetmod(b->ptr, (char)((num & BIO_FP_TEXT) ? 't' : 'b')); 232 else 233 # endif 234 { 235 # if defined(OPENSSL_SYS_WINDOWS) 236 int fd = _fileno((FILE *)ptr); 237 if (num & BIO_FP_TEXT) 238 _setmode(fd, _O_TEXT); 239 else 240 _setmode(fd, _O_BINARY); 241 # elif defined(OPENSSL_SYS_MSDOS) 242 int fd = fileno((FILE *)ptr); 243 /* Set correct text/binary mode */ 244 if (num & BIO_FP_TEXT) 245 _setmode(fd, _O_TEXT); 246 /* Dangerous to set stdin/stdout to raw (unless redirected) */ 247 else { 248 if (fd == STDIN_FILENO || fd == STDOUT_FILENO) { 249 if (isatty(fd) <= 0) 250 _setmode(fd, _O_BINARY); 251 } else 252 _setmode(fd, _O_BINARY); 253 } 254 # elif defined(OPENSSL_SYS_WIN32_CYGWIN) 255 int fd = fileno((FILE *)ptr); 256 if (num & BIO_FP_TEXT) 257 setmode(fd, O_TEXT); 258 else 259 setmode(fd, O_BINARY); 260 # endif 261 } 262 break; 263 case BIO_C_SET_FILENAME: 264 file_free(b); 265 b->shutdown = (int)num & BIO_CLOSE; 266 if (num & BIO_FP_APPEND) { 267 if (num & BIO_FP_READ) 268 OPENSSL_strlcpy(p, "a+", sizeof(p)); 269 else 270 OPENSSL_strlcpy(p, "a", sizeof(p)); 271 } else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) 272 OPENSSL_strlcpy(p, "r+", sizeof(p)); 273 else if (num & BIO_FP_WRITE) 274 OPENSSL_strlcpy(p, "w", sizeof(p)); 275 else if (num & BIO_FP_READ) 276 OPENSSL_strlcpy(p, "r", sizeof(p)); 277 else { 278 BIOerr(BIO_F_FILE_CTRL, BIO_R_BAD_FOPEN_MODE); 279 ret = 0; 280 break; 281 } 282 # if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32_CYGWIN) 283 if (!(num & BIO_FP_TEXT)) 284 OPENSSL_strlcat(p, "b", sizeof(p)); 285 else 286 OPENSSL_strlcat(p, "t", sizeof(p)); 287 # endif 288 fp = openssl_fopen(ptr, p); 289 if (fp == NULL) { 290 SYSerr(SYS_F_FOPEN, get_last_sys_error()); 291 ERR_add_error_data(5, "fopen('", ptr, "','", p, "')"); 292 BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB); 293 ret = 0; 294 break; 295 } 296 b->ptr = fp; 297 b->init = 1; 298 BIO_clear_flags(b, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage 299 * UPLINK */ 300 break; 301 case BIO_C_GET_FILE_PTR: 302 /* the ptr parameter is actually a FILE ** in this case. */ 303 if (ptr != NULL) { 304 fpp = (FILE **)ptr; 305 *fpp = (FILE *)b->ptr; 306 } 307 break; 308 case BIO_CTRL_GET_CLOSE: 309 ret = (long)b->shutdown; 310 break; 311 case BIO_CTRL_SET_CLOSE: 312 b->shutdown = (int)num; 313 break; 314 case BIO_CTRL_FLUSH: 315 st = b->flags & BIO_FLAGS_UPLINK 316 ? UP_fflush(b->ptr) : fflush((FILE *)b->ptr); 317 if (st == EOF) { 318 SYSerr(SYS_F_FFLUSH, get_last_sys_error()); 319 ERR_add_error_data(1, "fflush()"); 320 BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB); 321 ret = 0; 322 } 323 break; 324 case BIO_CTRL_DUP: 325 ret = 1; 326 break; 327 328 case BIO_CTRL_WPENDING: 329 case BIO_CTRL_PENDING: 330 case BIO_CTRL_PUSH: 331 case BIO_CTRL_POP: 332 default: 333 ret = 0; 334 break; 335 } 336 return ret; 337 } 338 339 static int file_gets(BIO *bp, char *buf, int size) 340 { 341 int ret = 0; 342 343 buf[0] = '\0'; 344 if (bp->flags & BIO_FLAGS_UPLINK) { 345 if (!UP_fgets(buf, size, bp->ptr)) 346 goto err; 347 } else { 348 if (!fgets(buf, size, (FILE *)bp->ptr)) 349 goto err; 350 } 351 if (buf[0] != '\0') 352 ret = strlen(buf); 353 err: 354 return ret; 355 } 356 357 static int file_puts(BIO *bp, const char *str) 358 { 359 int n, ret; 360 361 n = strlen(str); 362 ret = file_write(bp, str, n); 363 return ret; 364 } 365 366 #else 367 368 static int file_write(BIO *b, const char *in, int inl) 369 { 370 return -1; 371 } 372 static int file_read(BIO *b, char *out, int outl) 373 { 374 return -1; 375 } 376 static int file_puts(BIO *bp, const char *str) 377 { 378 return -1; 379 } 380 static int file_gets(BIO *bp, char *buf, int size) 381 { 382 return 0; 383 } 384 static long file_ctrl(BIO *b, int cmd, long num, void *ptr) 385 { 386 return 0; 387 } 388 static int file_new(BIO *bi) 389 { 390 return 0; 391 } 392 static int file_free(BIO *a) 393 { 394 return 0; 395 } 396 397 static const BIO_METHOD methods_filep = { 398 BIO_TYPE_FILE, 399 "FILE pointer", 400 /* TODO: Convert to new style write function */ 401 bwrite_conv, 402 file_write, 403 /* TODO: Convert to new style read function */ 404 bread_conv, 405 file_read, 406 file_puts, 407 file_gets, 408 file_ctrl, 409 file_new, 410 file_free, 411 NULL, /* file_callback_ctrl */ 412 }; 413 414 const BIO_METHOD *BIO_s_file(void) 415 { 416 return &methods_filep; 417 } 418 419 BIO *BIO_new_file(const char *filename, const char *mode) 420 { 421 return NULL; 422 } 423 424 # endif /* OPENSSL_NO_STDIO */ 425 426 #endif /* HEADER_BSS_FILE_C */ 427