1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include <errno.h> 12e1051a39Sopenharmony_ci 13e1051a39Sopenharmony_ci#include "bio_local.h" 14e1051a39Sopenharmony_ci 15e1051a39Sopenharmony_ci#if defined(OPENSSL_NO_POSIX_IO) 16e1051a39Sopenharmony_ci/* 17e1051a39Sopenharmony_ci * Dummy placeholder for BIO_s_fd... 18e1051a39Sopenharmony_ci */ 19e1051a39Sopenharmony_ciBIO *BIO_new_fd(int fd, int close_flag) 20e1051a39Sopenharmony_ci{ 21e1051a39Sopenharmony_ci return NULL; 22e1051a39Sopenharmony_ci} 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ciint BIO_fd_non_fatal_error(int err) 25e1051a39Sopenharmony_ci{ 26e1051a39Sopenharmony_ci return 0; 27e1051a39Sopenharmony_ci} 28e1051a39Sopenharmony_ci 29e1051a39Sopenharmony_ciint BIO_fd_should_retry(int i) 30e1051a39Sopenharmony_ci{ 31e1051a39Sopenharmony_ci return 0; 32e1051a39Sopenharmony_ci} 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_ciconst BIO_METHOD *BIO_s_fd(void) 35e1051a39Sopenharmony_ci{ 36e1051a39Sopenharmony_ci return NULL; 37e1051a39Sopenharmony_ci} 38e1051a39Sopenharmony_ci#else 39e1051a39Sopenharmony_ci/* 40e1051a39Sopenharmony_ci * As for unconditional usage of "UPLINK" interface in this module. 41e1051a39Sopenharmony_ci * Trouble is that unlike Unix file descriptors [which are indexes 42e1051a39Sopenharmony_ci * in kernel-side per-process table], corresponding descriptors on 43e1051a39Sopenharmony_ci * platforms which require "UPLINK" interface seem to be indexes 44e1051a39Sopenharmony_ci * in a user-land, non-global table. Well, in fact they are indexes 45e1051a39Sopenharmony_ci * in stdio _iob[], and recall that _iob[] was the very reason why 46e1051a39Sopenharmony_ci * "UPLINK" interface was introduced in first place. But one way on 47e1051a39Sopenharmony_ci * another. Neither libcrypto or libssl use this BIO meaning that 48e1051a39Sopenharmony_ci * file descriptors can only be provided by application. Therefore 49e1051a39Sopenharmony_ci * "UPLINK" calls are due... 50e1051a39Sopenharmony_ci */ 51e1051a39Sopenharmony_cistatic int fd_write(BIO *h, const char *buf, int num); 52e1051a39Sopenharmony_cistatic int fd_read(BIO *h, char *buf, int size); 53e1051a39Sopenharmony_cistatic int fd_puts(BIO *h, const char *str); 54e1051a39Sopenharmony_cistatic int fd_gets(BIO *h, char *buf, int size); 55e1051a39Sopenharmony_cistatic long fd_ctrl(BIO *h, int cmd, long arg1, void *arg2); 56e1051a39Sopenharmony_cistatic int fd_new(BIO *h); 57e1051a39Sopenharmony_cistatic int fd_free(BIO *data); 58e1051a39Sopenharmony_ciint BIO_fd_should_retry(int s); 59e1051a39Sopenharmony_ci 60e1051a39Sopenharmony_cistatic const BIO_METHOD methods_fdp = { 61e1051a39Sopenharmony_ci BIO_TYPE_FD, 62e1051a39Sopenharmony_ci "file descriptor", 63e1051a39Sopenharmony_ci bwrite_conv, 64e1051a39Sopenharmony_ci fd_write, 65e1051a39Sopenharmony_ci bread_conv, 66e1051a39Sopenharmony_ci fd_read, 67e1051a39Sopenharmony_ci fd_puts, 68e1051a39Sopenharmony_ci fd_gets, 69e1051a39Sopenharmony_ci fd_ctrl, 70e1051a39Sopenharmony_ci fd_new, 71e1051a39Sopenharmony_ci fd_free, 72e1051a39Sopenharmony_ci NULL, /* fd_callback_ctrl */ 73e1051a39Sopenharmony_ci}; 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_ciconst BIO_METHOD *BIO_s_fd(void) 76e1051a39Sopenharmony_ci{ 77e1051a39Sopenharmony_ci return &methods_fdp; 78e1051a39Sopenharmony_ci} 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_ciBIO *BIO_new_fd(int fd, int close_flag) 81e1051a39Sopenharmony_ci{ 82e1051a39Sopenharmony_ci BIO *ret; 83e1051a39Sopenharmony_ci ret = BIO_new(BIO_s_fd()); 84e1051a39Sopenharmony_ci if (ret == NULL) 85e1051a39Sopenharmony_ci return NULL; 86e1051a39Sopenharmony_ci BIO_set_fd(ret, fd, close_flag); 87e1051a39Sopenharmony_ci return ret; 88e1051a39Sopenharmony_ci} 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_cistatic int fd_new(BIO *bi) 91e1051a39Sopenharmony_ci{ 92e1051a39Sopenharmony_ci bi->init = 0; 93e1051a39Sopenharmony_ci bi->num = -1; 94e1051a39Sopenharmony_ci bi->ptr = NULL; 95e1051a39Sopenharmony_ci bi->flags = BIO_FLAGS_UPLINK_INTERNAL; /* essentially redundant */ 96e1051a39Sopenharmony_ci return 1; 97e1051a39Sopenharmony_ci} 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_cistatic int fd_free(BIO *a) 100e1051a39Sopenharmony_ci{ 101e1051a39Sopenharmony_ci if (a == NULL) 102e1051a39Sopenharmony_ci return 0; 103e1051a39Sopenharmony_ci if (a->shutdown) { 104e1051a39Sopenharmony_ci if (a->init) { 105e1051a39Sopenharmony_ci UP_close(a->num); 106e1051a39Sopenharmony_ci } 107e1051a39Sopenharmony_ci a->init = 0; 108e1051a39Sopenharmony_ci a->flags = BIO_FLAGS_UPLINK_INTERNAL; 109e1051a39Sopenharmony_ci } 110e1051a39Sopenharmony_ci return 1; 111e1051a39Sopenharmony_ci} 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_cistatic int fd_read(BIO *b, char *out, int outl) 114e1051a39Sopenharmony_ci{ 115e1051a39Sopenharmony_ci int ret = 0; 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_ci if (out != NULL) { 118e1051a39Sopenharmony_ci clear_sys_error(); 119e1051a39Sopenharmony_ci ret = UP_read(b->num, out, outl); 120e1051a39Sopenharmony_ci BIO_clear_retry_flags(b); 121e1051a39Sopenharmony_ci if (ret <= 0) { 122e1051a39Sopenharmony_ci if (BIO_fd_should_retry(ret)) 123e1051a39Sopenharmony_ci BIO_set_retry_read(b); 124e1051a39Sopenharmony_ci else if (ret == 0) 125e1051a39Sopenharmony_ci b->flags |= BIO_FLAGS_IN_EOF; 126e1051a39Sopenharmony_ci } 127e1051a39Sopenharmony_ci } 128e1051a39Sopenharmony_ci return ret; 129e1051a39Sopenharmony_ci} 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_cistatic int fd_write(BIO *b, const char *in, int inl) 132e1051a39Sopenharmony_ci{ 133e1051a39Sopenharmony_ci int ret; 134e1051a39Sopenharmony_ci clear_sys_error(); 135e1051a39Sopenharmony_ci ret = UP_write(b->num, in, inl); 136e1051a39Sopenharmony_ci BIO_clear_retry_flags(b); 137e1051a39Sopenharmony_ci if (ret <= 0) { 138e1051a39Sopenharmony_ci if (BIO_fd_should_retry(ret)) 139e1051a39Sopenharmony_ci BIO_set_retry_write(b); 140e1051a39Sopenharmony_ci } 141e1051a39Sopenharmony_ci return ret; 142e1051a39Sopenharmony_ci} 143e1051a39Sopenharmony_ci 144e1051a39Sopenharmony_cistatic long fd_ctrl(BIO *b, int cmd, long num, void *ptr) 145e1051a39Sopenharmony_ci{ 146e1051a39Sopenharmony_ci long ret = 1; 147e1051a39Sopenharmony_ci int *ip; 148e1051a39Sopenharmony_ci 149e1051a39Sopenharmony_ci switch (cmd) { 150e1051a39Sopenharmony_ci case BIO_CTRL_RESET: 151e1051a39Sopenharmony_ci num = 0; 152e1051a39Sopenharmony_ci /* fall thru */ 153e1051a39Sopenharmony_ci case BIO_C_FILE_SEEK: 154e1051a39Sopenharmony_ci ret = (long)UP_lseek(b->num, num, 0); 155e1051a39Sopenharmony_ci break; 156e1051a39Sopenharmony_ci case BIO_C_FILE_TELL: 157e1051a39Sopenharmony_ci case BIO_CTRL_INFO: 158e1051a39Sopenharmony_ci ret = (long)UP_lseek(b->num, 0, 1); 159e1051a39Sopenharmony_ci break; 160e1051a39Sopenharmony_ci case BIO_C_SET_FD: 161e1051a39Sopenharmony_ci fd_free(b); 162e1051a39Sopenharmony_ci b->num = *((int *)ptr); 163e1051a39Sopenharmony_ci b->shutdown = (int)num; 164e1051a39Sopenharmony_ci b->init = 1; 165e1051a39Sopenharmony_ci break; 166e1051a39Sopenharmony_ci case BIO_C_GET_FD: 167e1051a39Sopenharmony_ci if (b->init) { 168e1051a39Sopenharmony_ci ip = (int *)ptr; 169e1051a39Sopenharmony_ci if (ip != NULL) 170e1051a39Sopenharmony_ci *ip = b->num; 171e1051a39Sopenharmony_ci ret = b->num; 172e1051a39Sopenharmony_ci } else 173e1051a39Sopenharmony_ci ret = -1; 174e1051a39Sopenharmony_ci break; 175e1051a39Sopenharmony_ci case BIO_CTRL_GET_CLOSE: 176e1051a39Sopenharmony_ci ret = b->shutdown; 177e1051a39Sopenharmony_ci break; 178e1051a39Sopenharmony_ci case BIO_CTRL_SET_CLOSE: 179e1051a39Sopenharmony_ci b->shutdown = (int)num; 180e1051a39Sopenharmony_ci break; 181e1051a39Sopenharmony_ci case BIO_CTRL_PENDING: 182e1051a39Sopenharmony_ci case BIO_CTRL_WPENDING: 183e1051a39Sopenharmony_ci ret = 0; 184e1051a39Sopenharmony_ci break; 185e1051a39Sopenharmony_ci case BIO_CTRL_DUP: 186e1051a39Sopenharmony_ci case BIO_CTRL_FLUSH: 187e1051a39Sopenharmony_ci ret = 1; 188e1051a39Sopenharmony_ci break; 189e1051a39Sopenharmony_ci case BIO_CTRL_EOF: 190e1051a39Sopenharmony_ci ret = (b->flags & BIO_FLAGS_IN_EOF) != 0; 191e1051a39Sopenharmony_ci break; 192e1051a39Sopenharmony_ci default: 193e1051a39Sopenharmony_ci ret = 0; 194e1051a39Sopenharmony_ci break; 195e1051a39Sopenharmony_ci } 196e1051a39Sopenharmony_ci return ret; 197e1051a39Sopenharmony_ci} 198e1051a39Sopenharmony_ci 199e1051a39Sopenharmony_cistatic int fd_puts(BIO *bp, const char *str) 200e1051a39Sopenharmony_ci{ 201e1051a39Sopenharmony_ci int n, ret; 202e1051a39Sopenharmony_ci 203e1051a39Sopenharmony_ci n = strlen(str); 204e1051a39Sopenharmony_ci ret = fd_write(bp, str, n); 205e1051a39Sopenharmony_ci return ret; 206e1051a39Sopenharmony_ci} 207e1051a39Sopenharmony_ci 208e1051a39Sopenharmony_cistatic int fd_gets(BIO *bp, char *buf, int size) 209e1051a39Sopenharmony_ci{ 210e1051a39Sopenharmony_ci int ret = 0; 211e1051a39Sopenharmony_ci char *ptr = buf; 212e1051a39Sopenharmony_ci char *end = buf + size - 1; 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_ci while (ptr < end && fd_read(bp, ptr, 1) > 0) { 215e1051a39Sopenharmony_ci if (*ptr++ == '\n') 216e1051a39Sopenharmony_ci break; 217e1051a39Sopenharmony_ci } 218e1051a39Sopenharmony_ci 219e1051a39Sopenharmony_ci ptr[0] = '\0'; 220e1051a39Sopenharmony_ci 221e1051a39Sopenharmony_ci if (buf[0] != '\0') 222e1051a39Sopenharmony_ci ret = strlen(buf); 223e1051a39Sopenharmony_ci return ret; 224e1051a39Sopenharmony_ci} 225e1051a39Sopenharmony_ci 226e1051a39Sopenharmony_ciint BIO_fd_should_retry(int i) 227e1051a39Sopenharmony_ci{ 228e1051a39Sopenharmony_ci int err; 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ci if ((i == 0) || (i == -1)) { 231e1051a39Sopenharmony_ci err = get_last_sys_error(); 232e1051a39Sopenharmony_ci 233e1051a39Sopenharmony_ci return BIO_fd_non_fatal_error(err); 234e1051a39Sopenharmony_ci } 235e1051a39Sopenharmony_ci return 0; 236e1051a39Sopenharmony_ci} 237e1051a39Sopenharmony_ci 238e1051a39Sopenharmony_ciint BIO_fd_non_fatal_error(int err) 239e1051a39Sopenharmony_ci{ 240e1051a39Sopenharmony_ci switch (err) { 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_ci# ifdef EWOULDBLOCK 243e1051a39Sopenharmony_ci# ifdef WSAEWOULDBLOCK 244e1051a39Sopenharmony_ci# if WSAEWOULDBLOCK != EWOULDBLOCK 245e1051a39Sopenharmony_ci case EWOULDBLOCK: 246e1051a39Sopenharmony_ci# endif 247e1051a39Sopenharmony_ci# else 248e1051a39Sopenharmony_ci case EWOULDBLOCK: 249e1051a39Sopenharmony_ci# endif 250e1051a39Sopenharmony_ci# endif 251e1051a39Sopenharmony_ci 252e1051a39Sopenharmony_ci# if defined(ENOTCONN) 253e1051a39Sopenharmony_ci case ENOTCONN: 254e1051a39Sopenharmony_ci# endif 255e1051a39Sopenharmony_ci 256e1051a39Sopenharmony_ci# ifdef EINTR 257e1051a39Sopenharmony_ci case EINTR: 258e1051a39Sopenharmony_ci# endif 259e1051a39Sopenharmony_ci 260e1051a39Sopenharmony_ci# ifdef EAGAIN 261e1051a39Sopenharmony_ci# if EWOULDBLOCK != EAGAIN 262e1051a39Sopenharmony_ci case EAGAIN: 263e1051a39Sopenharmony_ci# endif 264e1051a39Sopenharmony_ci# endif 265e1051a39Sopenharmony_ci 266e1051a39Sopenharmony_ci# ifdef EPROTO 267e1051a39Sopenharmony_ci case EPROTO: 268e1051a39Sopenharmony_ci# endif 269e1051a39Sopenharmony_ci 270e1051a39Sopenharmony_ci# ifdef EINPROGRESS 271e1051a39Sopenharmony_ci case EINPROGRESS: 272e1051a39Sopenharmony_ci# endif 273e1051a39Sopenharmony_ci 274e1051a39Sopenharmony_ci# ifdef EALREADY 275e1051a39Sopenharmony_ci case EALREADY: 276e1051a39Sopenharmony_ci# endif 277e1051a39Sopenharmony_ci return 1; 278e1051a39Sopenharmony_ci default: 279e1051a39Sopenharmony_ci break; 280e1051a39Sopenharmony_ci } 281e1051a39Sopenharmony_ci return 0; 282e1051a39Sopenharmony_ci} 283e1051a39Sopenharmony_ci#endif 284