1#include "network_backends.h" 2 3#if defined(USE_OPENSSL) 4 5#include "network.h" 6#include "log.h" 7 8#include <unistd.h> 9#include <stdlib.h> 10 11#include <errno.h> 12#include <string.h> 13 14#include <openssl/ssl.h> 15#include <openssl/err.h> 16 17#define DBE 0 18 19static int load_next_chunk(server *srv, connection *con, chunkqueue *cq, off_t max_bytes, const char **data, size_t *data_len) { 20 chunk * const c = cq->first; 21 22#define LOCAL_SEND_BUFSIZE (64 * 1024) 23 /* this is a 64k sendbuffer 24 * 25 * it has to stay at the same location all the time to satisfy the needs 26 * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE 27 * 28 * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown 29 * -> we expect a 64k block to 'leak' in valgrind 30 * */ 31 static char *local_send_buffer = NULL; 32 33 force_assert(NULL != c); 34 35 switch (c->type) { 36 case MEM_CHUNK: 37 { 38 size_t have; 39 40 force_assert(c->offset >= 0 && c->offset <= (off_t)buffer_string_length(c->mem)); 41 42 have = buffer_string_length(c->mem) - c->offset; 43 if ((off_t) have > max_bytes) have = max_bytes; 44 45 *data = c->mem->ptr + c->offset; 46 *data_len = have; 47 } 48 return 0; 49 50 case FILE_CHUNK: 51 Cdbg(DBE, "FILE_CHUNK: c->file.name=%s", c->file.name->ptr); 52 if (NULL == local_send_buffer) { 53 local_send_buffer = malloc(LOCAL_SEND_BUFSIZE); 54 force_assert(NULL != local_send_buffer); 55 } 56 57 if (0 != network_open_file_chunk(srv, con, cq)) return -1; 58 59 { 60 off_t offset, toSend; 61 62 force_assert(c->offset >= 0 && c->offset <= c->file.length); 63 offset = c->file.start + c->offset; 64 toSend = c->file.length - c->offset; 65 66 if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE; 67 if (toSend > max_bytes) toSend = max_bytes; 68 69 if (-1 == lseek(c->file.fd, offset, SEEK_SET)) { 70 log_error_write(srv, __FILE__, __LINE__, "ss", "lseek: ", strerror(errno)); 71 return -1; 72 } 73 if (-1 == (toSend = read(c->file.fd, local_send_buffer, toSend))) { 74 log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno)); 75 return -1; 76 } 77 78 *data = local_send_buffer; 79 *data_len = toSend; 80 } 81 return 0; 82 83 case SMB_CHUNK: 84 Cdbg(DBE, "SMB_CHUNK: c->file.name=%s", c->file.name->ptr); 85 if (NULL == local_send_buffer) { 86 local_send_buffer = malloc(LOCAL_SEND_BUFSIZE); 87 force_assert(NULL != local_send_buffer); 88 } 89 90 if (0 != network_open_file_chunk(srv, con, cq)) return -1; 91 92 { 93 off_t offset, toSend; 94 95 force_assert(c->offset >= 0 && c->offset <= c->file.length); 96 offset = c->file.start + c->offset; 97 toSend = c->file.length - c->offset; 98 99 if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE; 100 if (toSend > max_bytes) toSend = max_bytes; 101 102 smbc_wrapper_lseek(con, c->file.fd, offset, SEEK_SET ); 103 104 Cdbg(DBE, "c->file.fd=[%d], c->file.length=[%lld]", c->file.fd, c->file.length); 105 Cdbg(DBE, "offset=[%lld], toSend=[%lld]", offset, toSend); 106 107 if (-1 == (toSend = (size_t)smbc_wrapper_read(con, c->file.fd, local_send_buffer, (size_t)toSend ))) { 108 log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno)); 109 smbc_wrapper_close(con, c->file.fd); 110 Cdbg(DBE, "ifd =%d, toSend =%d, errno=%s", c->file.fd, toSend, strerror(errno)); 111 return -1; 112 } 113 114 *data = local_send_buffer; 115 *data_len = toSend; 116 } 117 return 0; 118 } 119 120 return -1; 121} 122 123 124int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq, off_t max_bytes) { 125 /* the remote side closed the connection before without shutdown request 126 * - IE 127 * - wget 128 * if keep-alive is disabled */ 129 130 if (con->keep_alive == 0) { 131 SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN); 132 } 133 134 chunkqueue_remove_finished_chunks(cq); 135 136 while (max_bytes > 0 && NULL != cq->first) { 137 const char *data; 138 size_t data_len; 139 int r; 140 141 if (0 != load_next_chunk(srv, con, cq, max_bytes, &data, &data_len)) return -1; 142 143 /** 144 * SSL_write man-page 145 * 146 * WARNING 147 * When an SSL_write() operation has to be repeated because of 148 * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be 149 * repeated with the same arguments. 150 */ 151 152 ERR_clear_error(); 153 r = SSL_write(ssl, data, data_len); 154 155 if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) { 156 log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection"); 157 return -1; 158 } 159 160 if (r <= 0) { 161 int ssl_r; 162 unsigned long err; 163 164 switch ((ssl_r = SSL_get_error(ssl, r))) { 165 case SSL_ERROR_WANT_WRITE: 166 return 0; /* try again later */ 167 case SSL_ERROR_SYSCALL: 168 /* perhaps we have error waiting in our error-queue */ 169 if (0 != (err = ERR_get_error())) { 170 do { 171 log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 172 ssl_r, r, 173 ERR_error_string(err, NULL)); 174 } while((err = ERR_get_error())); 175 } else if (r == -1) { 176 /* no, but we have errno */ 177 switch(errno) { 178 case EPIPE: 179 case ECONNRESET: 180 return -2; 181 default: 182 log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", 183 ssl_r, r, errno, 184 strerror(errno)); 185 break; 186 } 187 } else { 188 /* neither error-queue nor errno ? */ 189 log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", 190 ssl_r, r, errno, 191 strerror(errno)); 192 } 193 break; 194 195 case SSL_ERROR_ZERO_RETURN: 196 /* clean shutdown on the remote side */ 197 198 if (r == 0) return -2; 199 200 /* fall through */ 201 default: 202 while((err = ERR_get_error())) { 203 log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", 204 ssl_r, r, 205 ERR_error_string(err, NULL)); 206 } 207 break; 208 } 209 return -1; 210 } 211 212 chunkqueue_mark_written(cq, r); 213 max_bytes -= r; 214 215 if ((size_t) r < data_len) break; /* try again later */ 216 } 217 218 return 0; 219} 220#endif /* USE_OPENSSL */ 221