File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / network_openssl.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:20:06 2014 UTC (10 years ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_35p0, v1_4_35, HEAD
lighttpd 1.4.35

    1: #include "network_backends.h"
    2: 
    3: #ifdef USE_OPENSSL
    4: 
    5: #include "network.h"
    6: #include "fdevent.h"
    7: #include "log.h"
    8: #include "stat_cache.h"
    9: 
   10: #include <sys/types.h>
   11: #include <sys/socket.h>
   12: #include <sys/stat.h>
   13: #include <sys/time.h>
   14: #include <sys/resource.h>
   15: 
   16: #include <netinet/in.h>
   17: #include <netinet/tcp.h>
   18: 
   19: #include <errno.h>
   20: #include <fcntl.h>
   21: #include <unistd.h>
   22: #include <netdb.h>
   23: #include <string.h>
   24: #include <stdlib.h>
   25: #include <assert.h>
   26: 
   27: # include <openssl/ssl.h>
   28: # include <openssl/err.h>
   29: 
   30: int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq, off_t max_bytes) {
   31: 	int ssl_r;
   32: 	chunk *c;
   33: 
   34: 	/* this is a 64k sendbuffer
   35: 	 *
   36: 	 * it has to stay at the same location all the time to satisfy the needs
   37: 	 * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
   38: 	 *
   39: 	 * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
   40: 	 * -> we expect a 64k block to 'leak' in valgrind
   41: 	 *
   42: 	 *
   43: 	 * In reality we would like to use mmap() but we don't have a guarantee that
   44: 	 * we get the same mmap() address for each call. On openbsd the mmap() address
   45: 	 * even randomized.
   46: 	 *   That means either we keep the mmap() open or we do a read() into a
   47: 	 * constant buffer
   48: 	 * */
   49: #define LOCAL_SEND_BUFSIZE (64 * 1024)
   50: 	static char *local_send_buffer = NULL;
   51: 
   52: 	/* the remote side closed the connection before without shutdown request
   53: 	 * - IE
   54: 	 * - wget
   55: 	 * if keep-alive is disabled */
   56: 
   57: 	if (con->keep_alive == 0) {
   58: 		SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
   59: 	}
   60: 
   61: 	for(c = cq->first; (max_bytes > 0) && (NULL != c); c = c->next) {
   62: 		int chunk_finished = 0;
   63: 
   64: 		switch(c->type) {
   65: 		case MEM_CHUNK: {
   66: 			char * offset;
   67: 			off_t toSend;
   68: 			ssize_t r;
   69: 
   70: 			if (c->mem->used == 0 || c->mem->used == 1) {
   71: 				chunk_finished = 1;
   72: 				break;
   73: 			}
   74: 
   75: 			offset = c->mem->ptr + c->offset;
   76: 			toSend = c->mem->used - 1 - c->offset;
   77: 			if (toSend > max_bytes) toSend = max_bytes;
   78: 
   79: 			/**
   80: 			 * SSL_write man-page
   81: 			 *
   82: 			 * WARNING
   83: 			 *        When an SSL_write() operation has to be repeated because of
   84: 			 *        SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
   85: 			 *        repeated with the same arguments.
   86: 			 *
   87: 			 */
   88: 
   89: 			ERR_clear_error();
   90: 			r = SSL_write(ssl, offset, toSend);
   91: 
   92: 			if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
   93: 				log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection");
   94: 				return -1;
   95: 			}
   96: 
   97: 			if (r <= 0) {
   98: 				unsigned long err;
   99: 
  100: 				switch ((ssl_r = SSL_get_error(ssl, r))) {
  101: 				case SSL_ERROR_WANT_WRITE:
  102: 					break;
  103: 				case SSL_ERROR_SYSCALL:
  104: 					/* perhaps we have error waiting in our error-queue */
  105: 					if (0 != (err = ERR_get_error())) {
  106: 						do {
  107: 							log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
  108: 									ssl_r, r,
  109: 									ERR_error_string(err, NULL));
  110: 						} while((err = ERR_get_error()));
  111: 					} else if (r == -1) {
  112: 						/* no, but we have errno */
  113: 						switch(errno) {
  114: 						case EPIPE:
  115: 						case ECONNRESET:
  116: 							return -2;
  117: 						default:
  118: 							log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
  119: 									ssl_r, r, errno,
  120: 									strerror(errno));
  121: 							break;
  122: 						}
  123: 					} else {
  124: 						/* neither error-queue nor errno ? */
  125: 						log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
  126: 								ssl_r, r, errno,
  127: 								strerror(errno));
  128: 					}
  129: 
  130: 					return  -1;
  131: 				case SSL_ERROR_ZERO_RETURN:
  132: 					/* clean shutdown on the remote side */
  133: 
  134: 					if (r == 0) return -2;
  135: 
  136: 					/* fall through */
  137: 				default:
  138: 					while((err = ERR_get_error())) {
  139: 						log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
  140: 								ssl_r, r,
  141: 								ERR_error_string(err, NULL));
  142: 					}
  143: 
  144: 					return  -1;
  145: 				}
  146: 			} else {
  147: 				c->offset += r;
  148: 				cq->bytes_out += r;
  149: 				max_bytes -= r;
  150: 			}
  151: 
  152: 			if (c->offset == (off_t)c->mem->used - 1) {
  153: 				chunk_finished = 1;
  154: 			}
  155: 
  156: 			break;
  157: 		}
  158: 		case FILE_CHUNK: {
  159: 			char *s;
  160: 			ssize_t r;
  161: 			stat_cache_entry *sce = NULL;
  162: 			int ifd;
  163: 			int write_wait = 0;
  164: 
  165: 			if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
  166: 				log_error_write(srv, __FILE__, __LINE__, "sb",
  167: 						strerror(errno), c->file.name);
  168: 				return -1;
  169: 			}
  170: 
  171: 			if (NULL == local_send_buffer) {
  172: 				local_send_buffer = malloc(LOCAL_SEND_BUFSIZE);
  173: 				force_assert(local_send_buffer);
  174: 			}
  175: 
  176: 			do {
  177: 				off_t offset = c->file.start + c->offset;
  178: 				off_t toSend = c->file.length - c->offset;
  179: 				if (toSend > max_bytes) toSend = max_bytes;
  180: 
  181: 				if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
  182: 
  183: 				if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
  184: 					log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
  185: 
  186: 					return -1;
  187: 				}
  188: 
  189: 
  190: 				if (-1 == lseek(ifd, offset, SEEK_SET)) {
  191: 					log_error_write(srv, __FILE__, __LINE__, "ss", "lseek failed:", strerror(errno));
  192: 					close(ifd);
  193: 					return -1;
  194: 				}
  195: 				if (-1 == (toSend = read(ifd, local_send_buffer, toSend))) {
  196: 					log_error_write(srv, __FILE__, __LINE__, "ss", "read failed:", strerror(errno));
  197: 					close(ifd);
  198: 					return -1;
  199: 				}
  200: 
  201: 				s = local_send_buffer;
  202: 
  203: 				close(ifd);
  204: 
  205: 				ERR_clear_error();
  206: 				r = SSL_write(ssl, s, toSend);
  207: 
  208: 				if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
  209: 					log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection");
  210: 					return -1;
  211: 				}
  212: 
  213: 				if (r <= 0) {
  214: 					unsigned long err;
  215: 
  216: 					switch ((ssl_r = SSL_get_error(ssl, r))) {
  217: 					case SSL_ERROR_WANT_WRITE:
  218: 						write_wait = 1;
  219: 						break;
  220: 					case SSL_ERROR_SYSCALL:
  221: 						/* perhaps we have error waiting in our error-queue */
  222: 						if (0 != (err = ERR_get_error())) {
  223: 							do {
  224: 								log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
  225: 										ssl_r, r,
  226: 										ERR_error_string(err, NULL));
  227: 							} while((err = ERR_get_error()));
  228: 						} else if (r == -1) {
  229: 							/* no, but we have errno */
  230: 							switch(errno) {
  231: 							case EPIPE:
  232: 							case ECONNRESET:
  233: 								return -2;
  234: 							default:
  235: 								log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
  236: 										ssl_r, r, errno,
  237: 										strerror(errno));
  238: 								break;
  239: 							}
  240: 						} else {
  241: 							/* neither error-queue nor errno ? */
  242: 							log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
  243: 									ssl_r, r, errno,
  244: 									strerror(errno));
  245: 						}
  246: 
  247: 						return  -1;
  248: 					case SSL_ERROR_ZERO_RETURN:
  249: 						/* clean shutdown on the remote side */
  250: 
  251: 						if (r == 0)  return -2;
  252: 
  253: 						/* fall thourgh */
  254: 					default:
  255: 						while((err = ERR_get_error())) {
  256: 							log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
  257: 									ssl_r, r,
  258: 									ERR_error_string(err, NULL));
  259: 						}
  260: 
  261: 						return -1;
  262: 					}
  263: 				} else {
  264: 					c->offset += r;
  265: 					cq->bytes_out += r;
  266: 					max_bytes -= r;
  267: 				}
  268: 
  269: 				if (c->offset == c->file.length) {
  270: 					chunk_finished = 1;
  271: 				}
  272: 			} while (!chunk_finished && !write_wait && max_bytes > 0);
  273: 
  274: 			break;
  275: 		}
  276: 		default:
  277: 			log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
  278: 
  279: 			return -1;
  280: 		}
  281: 
  282: 		if (!chunk_finished) {
  283: 			/* not finished yet */
  284: 
  285: 			break;
  286: 		}
  287: 	}
  288: 
  289: 	return 0;
  290: }
  291: #endif
  292: 
  293: #if 0
  294: network_openssl_init(void) {
  295: 	p->write_ssl = network_openssl_write_chunkset;
  296: }
  297: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>